aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeBitmapHeapscan.c
diff options
context:
space:
mode:
authorMelanie Plageman <melanieplageman@gmail.com>2025-01-30 15:26:55 -0500
committerMelanie Plageman <melanieplageman@gmail.com>2025-01-30 15:28:33 -0500
commita5358c14b2fe2210a1ac0b836f8d54723043fba2 (patch)
tree1bba2e0c58b6ee76e167e820af109ef332885127 /src/backend/executor/nodeBitmapHeapscan.c
parent115a365519bfd53a65bf17d253b26902eff0c337 (diff)
downloadpostgresql-a5358c14b2fe2210a1ac0b836f8d54723043fba2.tar.gz
postgresql-a5358c14b2fe2210a1ac0b836f8d54723043fba2.zip
Move BitmapTableScan per-scan setup into a helper
Add BitmapTableScanSetup(), a helper which contains all of the code that must be done on every scan of the table in a bitmap table scan. This includes scanning the index, building the bitmap, and setting up the scan descriptors. Pushing this setup into a helper function makes BitmapHeapNext() more readable. Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com> Discussion: https://postgr.es/m/CAN55FZ1vXu%2BZdT0_MM-i1vbTdfHHf0KR3cK6R5gs6dNNNpyrJw%40mail.gmail.com
Diffstat (limited to 'src/backend/executor/nodeBitmapHeapscan.c')
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c206
1 files changed, 107 insertions, 99 deletions
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index be616683f98..be0d24d901b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -48,6 +48,7 @@
#include "utils/rel.h"
#include "utils/spccache.h"
+static void BitmapTableScanSetup(BitmapHeapScanState *node);
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
@@ -57,6 +58,107 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
+/*
+ * Do the underlying index scan, build the bitmap, set up the parallel state
+ * needed for parallel workers to iterate through the bitmap, and set up the
+ * underlying table scan descriptor.
+ *
+ * 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
+ * node->prefetch_maximum. This is to avoid doing a lot of prefetching in a
+ * scan that stops after a few tuples because of a LIMIT.
+ */
+static void
+BitmapTableScanSetup(BitmapHeapScanState *node)
+{
+ TBMIterator tbmiterator = {0};
+ ParallelBitmapHeapState *pstate = node->pstate;
+ dsa_area *dsa = node->ss.ps.state->es_query_dsa;
+
+ if (!pstate)
+ {
+ node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+
+ if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
+ }
+ 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.
+ */
+ node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
+ if (!node->tbm || !IsA(node->tbm, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
+
+ /*
+ * 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(node->tbm);
+
+#ifdef USE_PREFETCH
+ if (node->prefetch_maximum > 0)
+ {
+ pstate->prefetch_iterator =
+ tbm_prepare_shared_iterate(node->tbm);
+ }
+#endif /* USE_PREFETCH */
+
+ /* We have initialized the shared state so wake up others. */
+ BitmapDoneInitializingSharedState(pstate);
+ }
+
+ tbmiterator = tbm_begin_iterate(node->tbm, dsa,
+ pstate ?
+ pstate->tbmiterator :
+ InvalidDsaPointer);
+
+#ifdef USE_PREFETCH
+ if (node->prefetch_maximum > 0)
+ node->prefetch_iterator =
+ tbm_begin_iterate(node->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.
+ */
+ if (!node->ss.ss_currentScanDesc)
+ {
+ bool need_tuples = false;
+
+ /*
+ * We can potentially skip fetching heap pages if we do not need any
+ * columns of the table, either for checking non-indexable quals or
+ * for returning data. This test is a bit simplistic, as it checks
+ * the stronger condition that there's no qual or return tlist at all.
+ * But in most cases it's probably not worth working harder than that.
+ */
+ need_tuples = (node->ss.ps.plan->qual != NIL ||
+ node->ss.ps.plan->targetlist != NIL);
+
+ node->ss.ss_currentScanDesc =
+ table_beginscan_bm(node->ss.ss_currentRelation,
+ node->ss.ps.state->es_snapshot,
+ 0,
+ NULL,
+ need_tuples);
+ }
+
+ node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
+ node->initialized = true;
+}
+
+
/* ----------------------------------------------------------------
* BitmapHeapNext
*
@@ -68,10 +170,11 @@ BitmapHeapNext(BitmapHeapScanState *node)
{
ExprContext *econtext;
TableScanDesc scan;
- TIDBitmap *tbm;
TupleTableSlot *slot;
+
+#ifdef USE_PREFETCH
ParallelBitmapHeapState *pstate = node->pstate;
- dsa_area *dsa = node->ss.ps.state->es_query_dsa;
+#endif
/*
* extract necessary information from index scan node
@@ -79,110 +182,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
scan = node->ss.ss_currentScanDesc;
- tbm = node->tbm;
/*
* 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
- * node->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)
{
- TBMIterator tbmiterator;
-
- if (!pstate)
- {
- tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
-
- if (!tbm || !IsA(tbm, TIDBitmap))
- elog(ERROR, "unrecognized result from subplan");
-
- node->tbm = tbm;
- }
- 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.
- */
- 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);
- }
-#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.
- */
- if (!scan)
- {
- bool need_tuples = false;
-
- /*
- * We can potentially skip fetching heap pages if we do not need
- * any columns of the table, either for checking non-indexable
- * quals or for returning data. This test is a bit simplistic, as
- * it checks the stronger condition that there's no qual or return
- * tlist at all. But in most cases it's probably not worth working
- * harder than that.
- */
- need_tuples = (node->ss.ps.plan->qual != NIL ||
- node->ss.ps.plan->targetlist != NIL);
-
- scan = table_beginscan_bm(node->ss.ss_currentRelation,
- node->ss.ps.state->es_snapshot,
- 0,
- NULL,
- need_tuples);
-
- node->ss.ss_currentScanDesc = scan;
- }
-
- scan->st.rs_tbmiterator = tbmiterator;
- node->initialized = true;
-
+ BitmapTableScanSetup(node);
+ scan = node->ss.ss_currentScanDesc;
goto new_page;
}