0001-Damage-control-for-planner-s-get_actual_variable_end.v3.patch
application/octet-stream
Filename: 0001-Damage-control-for-planner-s-get_actual_variable_end.v3.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v3-0001
| File | + | − |
|---|---|---|
| src/backend/utils/adt/selfuncs.c | 32 | 2 |
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index e0aeaa6909..9d86b8dbe7 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -6161,6 +6161,8 @@ get_actual_variable_endpoint(Relation heapRel,
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
MemoryContext oldcontext;
+ uint32 visited_heap_pages = 0;
+ BlockNumber last_heap_block = InvalidBlockNumber;
/*
* We use the index-only-scan machinery for this. With mostly-static
@@ -6213,13 +6215,41 @@ get_actual_variable_endpoint(Relation heapRel,
/* Fetch first/next tuple in specified direction */
while ((tid = index_getnext_tid(index_scan, indexscandir)) != NULL)
{
+ BlockNumber block = ItemPointerGetBlockNumber(tid);
+
if (!VM_ALL_VISIBLE(heapRel,
- ItemPointerGetBlockNumber(tid),
+ block,
&vmbuffer))
{
/* Rats, we have to visit the heap to check visibility */
if (!index_fetch_heap(index_scan, tableslot))
- continue; /* no visible tuple, try next index entry */
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ /*
+ * Use a simple test to see if we read a new block.
+ * This clearly isn't accurate for all access patterns
+ * but the only user of this information is the
+ * simple heuristic below.
+ */
+ if (block != last_heap_block)
+ visited_heap_pages++;
+
+ /*
+ * Apply a simple heuristic to avoid time-consuming
+ * scans through dead entries, if they exist.
+ * If we exceed the limit, simply break and return,
+ * which causes us to use the default selectivity.
+ */
+#define VISITED_PAGES_LIMIT 100
+ if (visited_heap_pages > VISITED_PAGES_LIMIT)
+ break;
+ else
+ {
+ last_heap_block = block;
+ continue; /* no visible tuple, try next index entry */
+ }
+ }
/* We don't actually need the heap tuple for anything */
ExecClearTuple(tableslot);