aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeBitmapHeapscan.c
diff options
context:
space:
mode:
authorMelanie Plageman <melanieplageman@gmail.com>2024-12-18 18:43:39 -0500
committerMelanie Plageman <melanieplageman@gmail.com>2024-12-18 18:43:39 -0500
commit1a0da347a7ac98db6964feb5e3063fc6e8fc92a0 (patch)
treefd98c7942a5acdc0d32377642a83cc67d4e01a52 /src/backend/executor/nodeBitmapHeapscan.c
parent7f9d4187e7bab10329cc00aff34cfba08248d4be (diff)
downloadpostgresql-1a0da347a7ac98db6964feb5e3063fc6e8fc92a0.tar.gz
postgresql-1a0da347a7ac98db6964feb5e3063fc6e8fc92a0.zip
Bitmap Table Scans use unified TBMIterator
With the repurposing of TBMIterator as an interface for both parallel and serial iteration through TIDBitmaps in commit 7f9d4187e7bab10329cc, bitmap table scans may now use it. Modify bitmap table scan code to use the TBMIterator. This requires moving around a bit of code, so a few variables are initialized elsewhere. Author: Melanie Plageman Reviewed-by: Tomas Vondra Discussion: https://postgr.es/m/c736f6aa-8b35-4e20-9621-62c7c82e2168%40vondra.me
Diffstat (limited to 'src/backend/executor/nodeBitmapHeapscan.c')
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c170
1 files changed, 69 insertions, 101 deletions
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index d9e7a516a07..a7cbaf1660e 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -95,8 +95,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
*/
if (!node->initialized)
{
- TBMPrivateIterator *tbmiterator = NULL;
- TBMSharedIterator *shared_tbmiterator = NULL;
+ TBMIterator tbmiterator;
if (!pstate)
{
@@ -106,70 +105,62 @@ BitmapHeapNext(BitmapHeapScanState *node)
elog(ERROR, "unrecognized result from subplan");
node->tbm = tbm;
- tbmiterator = tbm_begin_private_iterate(tbm);
#ifdef USE_PREFETCH
if (node->prefetch_maximum > 0)
- {
- node->prefetch_iterator = tbm_begin_private_iterate(tbm);
- node->prefetch_pages = 0;
- node->prefetch_target = -1;
- }
+ node->prefetch_iterator =
+ tbm_begin_iterate(node->tbm, dsa,
+ pstate ?
+ pstate->prefetch_iterator :
+ InvalidDsaPointer);
#endif /* USE_PREFETCH */
}
- else
+ else if (BitmapShouldInitializeSharedState(pstate))
{
/*
* The leader will immediately come out of the function, but
* others will be blocked until leader populates the TBM and wakes
* them up.
*/
- if (BitmapShouldInitializeSharedState(pstate))
- {
- tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
- if (!tbm || !IsA(tbm, TIDBitmap))
- elog(ERROR, "unrecognized result from subplan");
-
- node->tbm = tbm;
-
- /*
- * Prepare to iterate over the TBM. This will return the
- * dsa_pointer of the iterator state which will be used by
- * multiple processes to iterate jointly.
- */
- pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
-#ifdef USE_PREFETCH
- if (node->prefetch_maximum > 0)
- {
- pstate->prefetch_iterator =
- tbm_prepare_shared_iterate(tbm);
-
- /*
- * We don't need the mutex here as we haven't yet woke up
- * others.
- */
- pstate->prefetch_pages = 0;
- pstate->prefetch_target = -1;
- }
-#endif
+ tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+ if (!tbm || !IsA(tbm, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
- /* We have initialized the shared state so wake up others. */
- BitmapDoneInitializingSharedState(pstate);
- }
+ node->tbm = tbm;
- /* Allocate a private iterator and attach the shared state to it */
- shared_tbmiterator =
- tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
+ /*
+ * Prepare to iterate over the TBM. This will return the
+ * dsa_pointer of the iterator state which will be used by
+ * multiple processes to iterate jointly.
+ */
+ pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
#ifdef USE_PREFETCH
if (node->prefetch_maximum > 0)
{
- node->shared_prefetch_iterator =
- tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
+ pstate->prefetch_iterator =
+ tbm_prepare_shared_iterate(tbm);
}
#endif /* USE_PREFETCH */
+
+ /* We have initialized the shared state so wake up others. */
+ BitmapDoneInitializingSharedState(pstate);
}
+ tbmiterator = tbm_begin_iterate(tbm, dsa,
+ pstate ?
+ pstate->tbmiterator :
+ InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+ if (node->prefetch_maximum > 0)
+ node->prefetch_iterator =
+ tbm_begin_iterate(tbm, dsa,
+ pstate ?
+ pstate->prefetch_iterator :
+ InvalidDsaPointer);
+#endif /* USE_PREFETCH */
+
/*
* If this is the first scan of the underlying table, create the table
* scan descriptor and begin the scan.
@@ -198,8 +189,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
node->ss.ss_currentScanDesc = scan;
}
- scan->st.bitmap.rs_iterator = tbmiterator;
- scan->st.bitmap.rs_shared_iterator = shared_tbmiterator;
+ scan->st.rs_tbmiterator = tbmiterator;
node->initialized = true;
goto new_page;
@@ -285,7 +275,7 @@ new_page:
* ahead of the current block.
*/
if (node->pstate == NULL &&
- node->prefetch_iterator &&
+ !tbm_exhausted(&node->prefetch_iterator) &&
node->prefetch_blockno < node->blockno)
elog(ERROR,
"prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
@@ -332,16 +322,16 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
if (pstate == NULL)
{
- TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+ TBMIterator *prefetch_iterator = &node->prefetch_iterator;
if (node->prefetch_pages > 0)
{
/* The main iterator has closed the distance by one page */
node->prefetch_pages--;
}
- else if (prefetch_iterator)
+ else if (!tbm_exhausted(prefetch_iterator))
{
- tbmpre = tbm_private_iterate(prefetch_iterator);
+ tbmpre = tbm_iterate(prefetch_iterator);
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
InvalidBlockNumber;
}
@@ -359,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
*/
if (node->prefetch_maximum > 0)
{
- TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+ TBMIterator *prefetch_iterator = &node->prefetch_iterator;
SpinLockAcquire(&pstate->mutex);
if (pstate->prefetch_pages > 0)
@@ -380,9 +370,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
* we don't validate the blockno here as we do in non-parallel
* case.
*/
- if (prefetch_iterator)
+ if (!tbm_exhausted(prefetch_iterator))
{
- tbmpre = tbm_shared_iterate(prefetch_iterator);
+ tbmpre = tbm_iterate(prefetch_iterator);
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
InvalidBlockNumber;
}
@@ -446,21 +436,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
if (pstate == NULL)
{
- TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
+ TBMIterator *prefetch_iterator = &node->prefetch_iterator;
- if (prefetch_iterator)
+ if (!tbm_exhausted(prefetch_iterator))
{
while (node->prefetch_pages < node->prefetch_target)
{
- TBMIterateResult *tbmpre;
+ TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
bool skip_fetch;
- tbmpre = tbm_private_iterate(prefetch_iterator);
if (tbmpre == NULL)
{
/* No more pages to prefetch */
- tbm_end_private_iterate(prefetch_iterator);
- node->prefetch_iterator = NULL;
+ tbm_end_iterate(prefetch_iterator);
break;
}
node->prefetch_pages++;
@@ -488,9 +476,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
if (pstate->prefetch_pages < pstate->prefetch_target)
{
- TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
+ TBMIterator *prefetch_iterator = &node->prefetch_iterator;
- if (prefetch_iterator)
+ if (!tbm_exhausted(prefetch_iterator))
{
while (1)
{
@@ -513,12 +501,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
if (!do_prefetch)
return;
- tbmpre = tbm_shared_iterate(prefetch_iterator);
+ tbmpre = tbm_iterate(prefetch_iterator);
if (tbmpre == NULL)
{
/* No more pages to prefetch */
- tbm_end_shared_iterate(prefetch_iterator);
- node->shared_prefetch_iterator = NULL;
+ tbm_end_iterate(prefetch_iterator);
break;
}
@@ -587,39 +574,30 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
/*
* End iteration on iterators saved in scan descriptor.
*/
- if (scan->st.bitmap.rs_shared_iterator)
- {
- tbm_end_shared_iterate(scan->st.bitmap.rs_shared_iterator);
- scan->st.bitmap.rs_shared_iterator = NULL;
- }
-
- if (scan->st.bitmap.rs_iterator)
- {
- tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
- scan->st.bitmap.rs_iterator = NULL;
- }
+ tbm_end_iterate(&scan->st.rs_tbmiterator);
/* rescan to release any page pin */
table_rescan(node->ss.ss_currentScanDesc, NULL);
}
+ /* If we did not already clean up the prefetch iterator, do so now. */
+ if (!tbm_exhausted(&node->prefetch_iterator))
+ tbm_end_iterate(&node->prefetch_iterator);
+
/* release bitmaps and buffers if any */
- if (node->prefetch_iterator)
- tbm_end_private_iterate(node->prefetch_iterator);
- if (node->shared_prefetch_iterator)
- tbm_end_shared_iterate(node->shared_prefetch_iterator);
if (node->tbm)
tbm_free(node->tbm);
if (node->pvmbuffer != InvalidBuffer)
ReleaseBuffer(node->pvmbuffer);
node->tbm = NULL;
- node->prefetch_iterator = NULL;
node->initialized = false;
- node->shared_prefetch_iterator = NULL;
node->pvmbuffer = InvalidBuffer;
node->recheck = true;
+ /* Only used for serial BHS */
node->blockno = InvalidBlockNumber;
node->prefetch_blockno = InvalidBlockNumber;
+ node->prefetch_pages = 0;
+ node->prefetch_target = -1;
ExecScanReScan(&node->ss);
@@ -678,17 +656,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
/*
* End iteration on iterators saved in scan descriptor.
*/
- if (scanDesc->st.bitmap.rs_shared_iterator)
- {
- tbm_end_shared_iterate(scanDesc->st.bitmap.rs_shared_iterator);
- scanDesc->st.bitmap.rs_shared_iterator = NULL;
- }
-
- if (scanDesc->st.bitmap.rs_iterator)
- {
- tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
- scanDesc->st.bitmap.rs_iterator = NULL;
- }
+ tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
/*
* close table scan
@@ -696,15 +664,15 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
table_endscan(scanDesc);
}
+ /* If we did not already clean up the prefetch iterator, do so now. */
+ if (!tbm_exhausted(&node->prefetch_iterator))
+ tbm_end_iterate(&node->prefetch_iterator);
+
/*
* release bitmaps and buffers if any
*/
- if (node->prefetch_iterator)
- tbm_end_private_iterate(node->prefetch_iterator);
if (node->tbm)
tbm_free(node->tbm);
- if (node->shared_prefetch_iterator)
- tbm_end_shared_iterate(node->shared_prefetch_iterator);
if (node->pvmbuffer != InvalidBuffer)
ReleaseBuffer(node->pvmbuffer);
}
@@ -744,11 +712,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
/* Zero the statistics counters */
memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
- scanstate->prefetch_iterator = NULL;
scanstate->prefetch_pages = 0;
- scanstate->prefetch_target = 0;
+ scanstate->prefetch_target = -1;
scanstate->initialized = false;
- scanstate->shared_prefetch_iterator = NULL;
scanstate->pstate = NULL;
scanstate->recheck = true;
scanstate->blockno = InvalidBlockNumber;
@@ -907,7 +873,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
/* Initialize the mutex */
SpinLockInit(&pstate->mutex);
pstate->prefetch_pages = 0;
- pstate->prefetch_target = 0;
+ pstate->prefetch_target = -1;
pstate->state = BM_INITIAL;
ConditionVariableInit(&pstate->cv);
@@ -944,6 +910,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
return;
pstate->state = BM_INITIAL;
+ pstate->prefetch_pages = 0;
+ pstate->prefetch_target = -1;
if (DsaPointerIsValid(pstate->tbmiterator))
tbm_free_shared_area(dsa, pstate->tbmiterator);