diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index d597b7e81f..c7a731c69f 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -6145,6 +6145,8 @@ get_actual_variable_endpoint(Relation heapRel, Datum values[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; MemoryContext oldcontext; + double endpoint_cost = 0.0; + BlockNumber last_block = InvalidBlockNumber; /* * We use the index-only-scan machinery for this. With mostly-static @@ -6197,13 +6199,26 @@ 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(); + if (block != last_block) + endpoint_cost += random_page_cost; + else + endpoint_cost += cpu_tuple_cost; + last_block = block; +#define ENDPOINT_COST_LIMIT 20.0 + if (endpoint_cost > ENDPOINT_COST_LIMIT) + break; + else + continue; /* no visible tuple, try next index entry */ + } /* We don't actually need the heap tuple for anything */ ExecClearTuple(tableslot);