public inbox for [email protected]
help / color / mirror / Atom feedFrom: Melanie Plageman <[email protected]>
Subject: [PATCH v8 17/17] BitmapHeapScan uses streaming read API
Date: Fri, 22 Mar 2024 16:51:40 -0400
Remove all of the code to do prefetching from BitmapHeapScan code and
rely on the streaming read API prefetching. Heap table AM implements a
streaming read callback which uses the iterator to get the next valid
block that needs to be fetched for the streaming read API.
ci-os-only:
---
src/backend/access/heap/heapam.c | 96 ++++--
src/backend/access/heap/heapam_handler.c | 346 +++-------------------
src/backend/executor/nodeBitmapHeapscan.c | 44 +--
src/include/access/heapam.h | 16 +-
src/include/access/relscan.h | 7 -
src/include/access/tableam.h | 16 -
src/include/nodes/execnodes.h | 9 +-
7 files changed, 116 insertions(+), 418 deletions(-)
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c12563a188..1beb0bb99b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -111,6 +111,8 @@ static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
bool *copy);
+static BlockNumber bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+ void *per_buffer_data);
/*
* Each tuple lock mode has a corresponding heavyweight lock, and one or two
@@ -331,6 +333,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
if (key != NULL && scan->rs_base.rs_nkeys > 0)
memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
+ if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+ {
+ if (scan->rs_pgsr)
+ pg_streaming_read_free(scan->rs_pgsr);
+
+ scan->rs_pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_DEFAULT,
+ scan,
+ sizeof(TBMIterateResult),
+ scan->rs_strategy,
+ BMR_REL(scan->rs_base.rs_rd),
+ MAIN_FORKNUM,
+ bitmapheap_pgsr_next);
+
+
+ }
+
/*
* Currently, we only have a stats counter for sequential heap scans (but
* e.g for bitmap scans the underlying bitmap index scans will be counted,
@@ -951,16 +969,9 @@ heap_beginscan(Relation relation, Snapshot snapshot,
scan->rs_base.rs_flags = flags;
scan->rs_base.rs_parallel = parallel_scan;
scan->rs_strategy = NULL; /* set in initscan */
-
- scan->rs_base.blockno = InvalidBlockNumber;
-
+ scan->rs_pgsr = NULL;
scan->rs_vmbuffer = InvalidBuffer;
scan->rs_empty_tuples_pending = 0;
- scan->pvmbuffer = InvalidBuffer;
-
- scan->pfblockno = InvalidBlockNumber;
- scan->prefetch_target = -1;
- scan->prefetch_pages = 0;
/*
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1043,12 +1054,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE;
}
- scan->rs_base.blockno = InvalidBlockNumber;
-
- scan->pfblockno = InvalidBlockNumber;
- scan->prefetch_target = -1;
- scan->prefetch_pages = 0;
-
/*
* unpin scan buffers
*/
@@ -1061,12 +1066,6 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
scan->rs_vmbuffer = InvalidBuffer;
}
- if (BufferIsValid(scan->pvmbuffer))
- {
- ReleaseBuffer(scan->pvmbuffer);
- scan->pvmbuffer = InvalidBuffer;
- }
-
/*
* reinitialize scan descriptor
*/
@@ -1092,12 +1091,6 @@ heap_endscan(TableScanDesc sscan)
scan->rs_vmbuffer = InvalidBuffer;
}
- if (BufferIsValid(scan->pvmbuffer))
- {
- ReleaseBuffer(scan->pvmbuffer);
- scan->pvmbuffer = InvalidBuffer;
- }
-
/*
* decrement relation reference count and free scan descriptor storage
*/
@@ -1115,6 +1108,9 @@ heap_endscan(TableScanDesc sscan)
if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
UnregisterSnapshot(scan->rs_base.rs_snapshot);
+ if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN && scan->rs_pgsr)
+ pg_streaming_read_free(scan->rs_pgsr);
+
pfree(scan);
}
@@ -10272,3 +10268,51 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
CheckForSerializableConflictOut(relation, xid, snapshot);
}
+
+static BlockNumber
+bitmapheap_pgsr_next(PgStreamingRead *pgsr, void *pgsr_private,
+ void *per_buffer_data)
+{
+ TBMIterateResult *tbmres = per_buffer_data;
+ HeapScanDesc hdesc = (HeapScanDesc) pgsr_private;
+
+ for (;;)
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ bhs_iterate(hdesc->rs_base.rs_tbmiterator, tbmres);
+
+ /* no more entries in the bitmap */
+ if (!BlockNumberIsValid(tbmres->blockno))
+ return InvalidBlockNumber;
+
+ /*
+ * Ignore any claimed entries past what we think is the end of the
+ * relation. It may have been extended after the start of our scan (we
+ * only hold an AccessShareLock, and it could be inserts from this
+ * backend). We don't take this optimization in SERIALIZABLE
+ * isolation though, as we need to examine all invisible tuples
+ * reachable by the index.
+ */
+ if (!IsolationIsSerializable() && tbmres->blockno >= hdesc->rs_nblocks)
+ continue;
+
+ /*
+ * We can skip fetching the heap page if we don't need any fields from
+ * the heap, the bitmap entries don't need rechecking, and all tuples
+ * on the page are visible to our transaction.
+ */
+ if (!(hdesc->rs_base.rs_flags & SO_NEED_TUPLE) &&
+ !tbmres->recheck &&
+ VM_ALL_VISIBLE(hdesc->rs_base.rs_rd, tbmres->blockno, &hdesc->rs_vmbuffer))
+ {
+ hdesc->rs_empty_tuples_pending += tbmres->ntuples;
+ continue;
+ }
+
+ return tbmres->blockno;
+ }
+
+ /* not reachable */
+ Assert(false);
+}
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 9dfc99d8fa..fe9ee5976f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -56,10 +56,6 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer,
static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan);
-static inline void BitmapAdjustPrefetchIterator(HeapScanDesc scan);
-static inline void BitmapAdjustPrefetchTarget(HeapScanDesc scan);
-static inline void BitmapPrefetch(HeapScanDesc scan);
-
static const TableAmRoutine heapam_methods;
@@ -2110,146 +2106,68 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths,
HEAP_USABLE_BYTES_PER_PAGE);
}
-/*
- * BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
- *
- * We keep track of how far the prefetch iterator is ahead of the main
- * iterator in prefetch_pages. For each block the main iterator returns, we
- * decrement prefetch_pages.
- */
-static inline void
-BitmapAdjustPrefetchIterator(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
- ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
- TBMIterateResult tbmpre;
-
- if (pstate == NULL)
- {
- if (scan->prefetch_pages > 0)
- {
- /* The main iterator has closed the distance by one page */
- scan->prefetch_pages--;
- }
- else if (scan->rs_base.rs_pf_tbmiterator)
- {
- /* Do not let the prefetch iterator get behind the main one */
- bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
- scan->pfblockno = tbmpre.blockno;
- }
- return;
- }
-
- /*
- * Adjusting the prefetch iterator before invoking
- * heapam_bitmap_next_block() keeps prefetch distance higher across the
- * parallel workers.
- */
- if (scan->rs_base.prefetch_maximum > 0)
- {
- SpinLockAcquire(&pstate->mutex);
- if (pstate->prefetch_pages > 0)
- {
- pstate->prefetch_pages--;
- SpinLockRelease(&pstate->mutex);
- }
- else
- {
- /* Release the mutex before iterating */
- SpinLockRelease(&pstate->mutex);
-
- /*
- * In case of shared mode, we can not ensure that the current
- * blockno of the main iterator and that of the prefetch iterator
- * are same. It's possible that whatever blockno we are
- * prefetching will be processed by another process. Therefore,
- * we don't validate the blockno here as we do in non-parallel
- * case.
- */
- if (scan->rs_base.rs_pf_tbmiterator)
- {
- bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
- scan->pfblockno = tbmpre.blockno;
- }
- }
- }
-#endif /* USE_PREFETCH */
-}
static bool
-heapam_scan_bitmap_next_block(TableScanDesc scan,
- bool *recheck, BlockNumber *blockno,
+heapam_scan_bitmap_next_block(TableScanDesc scan, bool *recheck,
long *lossy_pages, long *exact_pages)
{
HeapScanDesc hscan = (HeapScanDesc) scan;
+ void *io_private;
BlockNumber block;
Buffer buffer;
Snapshot snapshot;
int ntup;
- TBMIterateResult tbmres;
+ TBMIterateResult *tbmres;
+
+ Assert(hscan->rs_pgsr);
hscan->rs_cindex = 0;
hscan->rs_ntuples = 0;
- *blockno = InvalidBlockNumber;
*recheck = true;
- BitmapAdjustPrefetchIterator(hscan);
-
- do
+ /* Release buffer containing previous block. */
+ if (BufferIsValid(hscan->rs_cbuf))
{
- CHECK_FOR_INTERRUPTS();
+ ReleaseBuffer(hscan->rs_cbuf);
+ hscan->rs_cbuf = InvalidBuffer;
+ }
- bhs_iterate(scan->rs_tbmiterator, &tbmres);
+ hscan->rs_cbuf = pg_streaming_read_buffer_get_next(hscan->rs_pgsr, &io_private);
- if (!BlockNumberIsValid(tbmres.blockno))
+ if (BufferIsInvalid(hscan->rs_cbuf))
+ {
+ if (BufferIsValid(hscan->rs_vmbuffer))
{
- /* no more entries in the bitmap */
- Assert(hscan->rs_empty_tuples_pending == 0);
- return false;
+ ReleaseBuffer(hscan->rs_vmbuffer);
+ hscan->rs_vmbuffer = InvalidBuffer;
}
/*
- * Ignore any claimed entries past what we think is the end of the
- * relation. It may have been extended after the start of our scan (we
- * only hold an AccessShareLock, and it could be inserts from this
- * backend). We don't take this optimization in SERIALIZABLE
- * isolation though, as we need to examine all invisible tuples
- * reachable by the index.
+ * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit
+ * all empty tuples at the end instead of emitting them per block we
+ * skip fetching. This is necessary because the streaming read API
+ * will only return TBMIterateResults for blocks actually fetched.
+ * When we skip fetching a block, we keep track of how many empty
+ * tuples to emit at the end of the BitmapHeapScan. We do not recheck
+ * all NULL tuples.
*/
- } while (!IsolationIsSerializable() && tbmres.blockno >= hscan->rs_nblocks);
+ *recheck = false;
+ return hscan->rs_empty_tuples_pending > 0;
+ }
- /* Got a valid block */
- *blockno = tbmres.blockno;
- *recheck = tbmres.recheck;
+ Assert(io_private);
- /*
- * We can skip fetching the heap page if we don't need any fields from the
- * heap, the bitmap entries don't need rechecking, and all tuples on the
- * page are visible to our transaction.
- */
- if (!(scan->rs_flags & SO_NEED_TUPLE) &&
- !tbmres.recheck &&
- VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &hscan->rs_vmbuffer))
- {
- /* can't be lossy in the skip_fetch case */
- Assert(tbmres.ntuples >= 0);
- Assert(hscan->rs_empty_tuples_pending >= 0);
+ tbmres = io_private;
- hscan->rs_empty_tuples_pending += tbmres.ntuples;
+ Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno);
- return true;
- }
+ *recheck = tbmres->recheck;
- block = tbmres.blockno;
+ hscan->rs_cblock = tbmres->blockno;
+ hscan->rs_ntuples = tbmres->ntuples;
- /*
- * Acquire pin on the target heap page, trading in any pin we held before.
- */
- hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf,
- scan->rs_rd,
- block);
- hscan->rs_cblock = block;
+ block = tbmres->blockno;
buffer = hscan->rs_cbuf;
snapshot = scan->rs_snapshot;
@@ -2270,7 +2188,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
/*
* We need two separate strategies for lossy and non-lossy cases.
*/
- if (tbmres.ntuples >= 0)
+ if (tbmres->ntuples >= 0)
{
/*
* Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,9 +2197,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
*/
int curslot;
- for (curslot = 0; curslot < tbmres.ntuples; curslot++)
+ for (curslot = 0; curslot < tbmres->ntuples; curslot++)
{
- OffsetNumber offnum = tbmres.offsets[curslot];
+ OffsetNumber offnum = tbmres->offsets[curslot];
ItemPointerData tid;
HeapTupleData heapTuple;
@@ -2331,23 +2249,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
Assert(ntup <= MaxHeapTuplesPerPage);
hscan->rs_ntuples = ntup;
- if (tbmres.ntuples < 0)
+ if (tbmres->ntuples < 0)
(*lossy_pages)++;
else
(*exact_pages)++;
- /*
- * If serial, we can error out if the the prefetch block doesn't stay
- * ahead of the current block.
- */
- if (scan->bm_parallel == NULL &&
- scan->rs_pf_tbmiterator &&
- hscan->pfblockno > hscan->rs_base.blockno)
- elog(ERROR, "prefetch and main iterators are out of sync");
-
- /* Adjust the prefetch target */
- BitmapAdjustPrefetchTarget(hscan);
-
/*
* Return true to indicate that a valid block was found and the bitmap is
* not exhausted. If there are no visible tuples on this page,
@@ -2358,152 +2264,6 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
return true;
}
-/*
- * BitmapAdjustPrefetchTarget - Adjust the prefetch target
- *
- * Increase prefetch target if it's not yet at the max. Note that
- * we will increase it to zero after fetching the very first
- * page/tuple, then to one after the second tuple is fetched, then
- * it doubles as later pages are fetched.
- */
-static inline void
-BitmapAdjustPrefetchTarget(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
- ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
- int prefetch_maximum = scan->rs_base.prefetch_maximum;
-
- if (pstate == NULL)
- {
- if (scan->prefetch_target >= prefetch_maximum)
- /* don't increase any further */ ;
- else if (scan->prefetch_target >= prefetch_maximum / 2)
- scan->prefetch_target = prefetch_maximum;
- else if (scan->prefetch_target > 0)
- scan->prefetch_target *= 2;
- else
- scan->prefetch_target++;
- return;
- }
-
- /* Do an unlocked check first to save spinlock acquisitions. */
- if (pstate->prefetch_target < prefetch_maximum)
- {
- SpinLockAcquire(&pstate->mutex);
- if (pstate->prefetch_target >= prefetch_maximum)
- /* don't increase any further */ ;
- else if (pstate->prefetch_target >= prefetch_maximum / 2)
- pstate->prefetch_target = prefetch_maximum;
- else if (pstate->prefetch_target > 0)
- pstate->prefetch_target *= 2;
- else
- pstate->prefetch_target++;
- SpinLockRelease(&pstate->mutex);
- }
-#endif /* USE_PREFETCH */
-}
-
-
-/*
- * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
- */
-static inline void
-BitmapPrefetch(HeapScanDesc scan)
-{
-#ifdef USE_PREFETCH
- ParallelBitmapHeapState *pstate = scan->rs_base.bm_parallel;
-
- if (pstate == NULL)
- {
- if (scan->rs_base.rs_pf_tbmiterator)
- {
- while (scan->prefetch_pages < scan->prefetch_target)
- {
- TBMIterateResult tbmpre;
- bool skip_fetch;
-
- bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
-
- if (!BlockNumberIsValid(tbmpre.blockno))
- {
- /* No more pages to prefetch */
- bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
- scan->rs_base.rs_pf_tbmiterator = NULL;
- break;
- }
- scan->prefetch_pages++;
- scan->pfblockno = tbmpre.blockno;
-
- /*
- * If we expect not to have to actually read this heap page,
- * skip this prefetch call, but continue to run the prefetch
- * logic normally. (Would it be better not to increment
- * prefetch_pages?)
- */
- skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
- !tbmpre.recheck &&
- VM_ALL_VISIBLE(scan->rs_base.rs_rd,
- tbmpre.blockno,
- &scan->pvmbuffer));
-
- if (!skip_fetch)
- PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
- }
- }
-
- return;
- }
-
- if (pstate->prefetch_pages < pstate->prefetch_target)
- {
- if (scan->rs_base.rs_pf_tbmiterator)
- {
- while (1)
- {
- TBMIterateResult tbmpre;
- bool do_prefetch = false;
- bool skip_fetch;
-
- /*
- * Recheck under the mutex. If some other process has already
- * done enough prefetching then we need not to do anything.
- */
- SpinLockAcquire(&pstate->mutex);
- if (pstate->prefetch_pages < pstate->prefetch_target)
- {
- pstate->prefetch_pages++;
- do_prefetch = true;
- }
- SpinLockRelease(&pstate->mutex);
-
- if (!do_prefetch)
- return;
-
- bhs_iterate(scan->rs_base.rs_pf_tbmiterator, &tbmpre);
- if (!BlockNumberIsValid(tbmpre.blockno))
- {
- /* No more pages to prefetch */
- bhs_end_iterate(scan->rs_base.rs_pf_tbmiterator);
- scan->rs_base.rs_pf_tbmiterator = NULL;
- break;
- }
-
- scan->pfblockno = tbmpre.blockno;
-
- /* As above, skip prefetch if we expect not to need page */
- skip_fetch = (!(scan->rs_base.rs_flags & SO_NEED_TUPLE) &&
- !tbmpre.recheck &&
- VM_ALL_VISIBLE(scan->rs_base.rs_rd,
- tbmpre.blockno,
- &scan->pvmbuffer));
-
- if (!skip_fetch)
- PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, tbmpre.blockno);
- }
- }
- }
-#endif /* USE_PREFETCH */
-}
/* ------------------------------------------------------------------------
* Executor related callbacks for the heap AM
@@ -2538,41 +2298,11 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
return true;
}
- if (!heapam_scan_bitmap_next_block(scan, recheck, &scan->blockno,
+ if (!heapam_scan_bitmap_next_block(scan, recheck,
lossy_pages, exact_pages))
return false;
}
-#ifdef USE_PREFETCH
-
- /*
- * Try to prefetch at least a few pages even before we get to the second
- * page if we don't stop reading after the first tuple.
- */
- if (!scan->bm_parallel)
- {
- if (hscan->prefetch_target < scan->prefetch_maximum)
- hscan->prefetch_target++;
- }
- else if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
- {
- /* take spinlock while updating shared state */
- SpinLockAcquire(&scan->bm_parallel->mutex);
- if (scan->bm_parallel->prefetch_target < scan->prefetch_maximum)
- scan->bm_parallel->prefetch_target++;
- SpinLockRelease(&scan->bm_parallel->mutex);
- }
-
- /*
- * We issue prefetch requests *after* fetching the current page to try to
- * avoid having prefetching interfere with the main I/O. Also, this should
- * happen only when we have determined there is still something to do on
- * the current page, else we may uselessly prefetch the same page we are
- * just about to request for real.
- */
- BitmapPrefetch(hscan);
-#endif /* USE_PREFETCH */
-
targoffset = hscan->rs_vistuples[hscan->rs_cindex];
page = BufferGetPage(hscan->rs_cbuf);
lp = PageGetItemId(page, targoffset);
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2683d8bc0c..c21dae466a 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -128,14 +128,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
/*
* If we haven't yet performed the underlying index scan, do it, and begin
* the iteration over the bitmap.
- *
- * For prefetching, we use *two* iterators, one for the pages we are
- * actually scanning and another that runs ahead of the first for
- * prefetching. node->prefetch_pages tracks exactly how many pages ahead
- * the prefetch iterator is. Also, node->prefetch_target tracks the
- * desired prefetch distance, which starts small and increases up to the
- * scan->prefetch_maximum. This is to avoid doing a lot of prefetching in
- * a scan that stops after a few tuples because of a LIMIT.
*/
if (!node->initialized)
{
@@ -146,15 +138,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
bool init_shared_state = node->pstate ?
BitmapShouldInitializeSharedState(node->pstate) : false;
- /*
- * Maximum number of prefetches for the tablespace if configured,
- * otherwise the current value of the effective_io_concurrency GUC.
- */
- int pf_maximum = 0;
-#ifdef USE_PREFETCH
- pf_maximum = get_tablespace_io_concurrency(node->ss.ss_currentRelation->rd_rel->reltablespace);
-#endif
-
if (!node->pstate || init_shared_state)
{
tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
@@ -171,13 +154,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
* multiple processes to iterate jointly.
*/
node->pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
- if (pf_maximum > 0)
- {
- node->pstate->prefetch_iterator =
- tbm_prepare_shared_iterate(tbm);
- }
-#endif
+
/* We have initialized the shared state so wake up others. */
BitmapDoneInitializingSharedState(node->pstate);
}
@@ -210,17 +187,10 @@ BitmapHeapNext(BitmapHeapScanState *node)
extra_flags);
}
- scan->prefetch_maximum = pf_maximum;
scan->bm_parallel = node->pstate;
scan->rs_tbmiterator = bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
-#ifdef USE_PREFETCH
- if (scan->prefetch_maximum > 0)
- bhs_begin_iterate(tbm, scan->bm_parallel, dsa);
-#endif /* USE_PREFETCH */
-
-
node->initialized = true;
}
@@ -319,7 +289,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
if (node->ss.ss_currentScanDesc)
table_rescan(node->ss.ss_currentScanDesc, NULL);
- /* release bitmaps and buffers if any */
+ /* release bitmaps if any */
if (node->tbm)
tbm_free(node->tbm);
node->tbm = NULL;
@@ -363,7 +333,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
table_endscan(scanDesc);
/*
- * release bitmaps and buffers if any
+ * release bitmaps if any
*/
if (node->tbm)
tbm_free(node->tbm);
@@ -519,14 +489,10 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
return;
pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
-
pstate->tbmiterator = 0;
- pstate->prefetch_iterator = 0;
/* Initialize the mutex */
SpinLockInit(&pstate->mutex);
- pstate->prefetch_pages = 0;
- pstate->prefetch_target = -1;
pstate->state = BM_INITIAL;
ConditionVariableInit(&pstate->cv);
@@ -557,11 +523,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
if (DsaPointerIsValid(pstate->tbmiterator))
tbm_free_shared_area(dsa, pstate->tbmiterator);
- if (DsaPointerIsValid(pstate->prefetch_iterator))
- tbm_free_shared_area(dsa, pstate->prefetch_iterator);
-
pstate->tbmiterator = InvalidDsaPointer;
- pstate->prefetch_iterator = InvalidDsaPointer;
}
/* ----------------------------------------------------------------
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 22bdccc2a9..1cad9c04f0 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -26,6 +26,7 @@
#include "storage/dsm.h"
#include "storage/lockdefs.h"
#include "storage/shm_toc.h"
+#include "storage/streaming_read.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
@@ -72,6 +73,9 @@ typedef struct HeapScanDescData
*/
ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
+ /* Streaming read control object for scans supporting it */
+ PgStreamingRead *rs_pgsr;
+
/*
* These fields are only used for bitmap scans for the "skip fetch"
* optimization. Bitmap scans needing no fields from the heap may skip
@@ -81,18 +85,6 @@ typedef struct HeapScanDescData
*/
Buffer rs_vmbuffer;
int rs_empty_tuples_pending;
- /* buffer for visibility-map lookups of prefetched pages */
- Buffer pvmbuffer;
-
- /*
- * These fields only used for prefetching in bitmap table scans
- */
- /* Current target for prefetch distance */
- int prefetch_target;
- /* # pages prefetch iterator is ahead of current */
- int prefetch_pages;
- /* used to validate prefetch block stays ahead of current block */
- BlockNumber pfblockno;
/* these fields only used in page-at-a-time mode and for bitmap scans */
int rs_cindex; /* current tuple's index in vistuples */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 65092d7226..00a123ee92 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -57,15 +57,8 @@ typedef struct TableScanDescData
/* Only used for Bitmap table scans */
BitmapHeapIterator *rs_tbmiterator;
- /* Prefetch iterator */
- BitmapHeapIterator *rs_pf_tbmiterator;
- /* maximum value for prefetch_target */
- int prefetch_maximum;
struct ParallelBitmapHeapState *bm_parallel;
- /* used to validate prefetch and current block stay in sync */
- BlockNumber blockno;
-
/*
* Information about type and behaviour of the scan, a bitmask of members
* of the ScanOptions enum (see tableam.h).
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 5ad3eff539..4bc021f0eb 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -933,7 +933,6 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
result = rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
result->rs_tbmiterator = NULL;
- result->rs_pf_tbmiterator = NULL;
result->bm_parallel = NULL;
return result;
}
@@ -999,13 +998,6 @@ table_endscan(TableScanDesc scan)
{
bhs_end_iterate(scan->rs_tbmiterator);
scan->rs_tbmiterator = NULL;
-#ifdef USE_PREFETCH
- if (scan->rs_pf_tbmiterator)
- {
- bhs_end_iterate(scan->rs_pf_tbmiterator);
- scan->rs_pf_tbmiterator = NULL;
- }
-#endif
}
scan->rs_rd->rd_tableam->scan_end(scan);
@@ -1022,14 +1014,6 @@ table_rescan(TableScanDesc scan,
{
bhs_end_iterate(scan->rs_tbmiterator);
scan->rs_tbmiterator = NULL;
-
-#ifdef USE_PREFETCH
- if (scan->rs_pf_tbmiterator)
- {
- bhs_end_iterate(scan->rs_pf_tbmiterator);
- scan->rs_pf_tbmiterator = NULL;
- }
-#endif
}
scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 7a3fdf9cd4..c1778653c7 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1758,11 +1758,7 @@ typedef enum
/* ----------------
* ParallelBitmapHeapState information
* tbmiterator iterator for scanning current pages
- * prefetch_iterator iterator for prefetching ahead of current page
- * mutex mutual exclusion for the prefetching variable
- * and state
- * prefetch_pages # pages prefetch iterator is ahead of current
- * prefetch_target current target prefetch distance
+ * mutex mutual exclusion for state
* state current state of the TIDBitmap
* cv conditional wait variable
* ----------------
@@ -1770,10 +1766,7 @@ typedef enum
typedef struct ParallelBitmapHeapState
{
dsa_pointer tbmiterator;
- dsa_pointer prefetch_iterator;
slock_t mutex;
- int prefetch_pages;
- int prefetch_target;
SharedBitmapState state;
ConditionVariable cv;
} ParallelBitmapHeapState;
--
2.40.1
--xqq4defy3uncu6k6--
view thread (39+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v8 17/17] BitmapHeapScan uses streaming read API
In-Reply-To: <no-message-id-1857192@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox