Skip to content

Commit a5358c1

Browse files
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
1 parent 115a365 commit a5358c1

File tree

1 file changed

+107
-99
lines changed

1 file changed

+107
-99
lines changed

src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 107 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "utils/rel.h"
4949
#include "utils/spccache.h"
5050

51+
static void BitmapTableScanSetup(BitmapHeapScanState *node);
5152
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
5253
static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
5354
static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node);
@@ -57,6 +58,107 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
5758
static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
5859

5960

61+
/*
62+
* Do the underlying index scan, build the bitmap, set up the parallel state
63+
* needed for parallel workers to iterate through the bitmap, and set up the
64+
* underlying table scan descriptor.
65+
*
66+
* For prefetching, we use *two* iterators, one for the pages we are actually
67+
* scanning and another that runs ahead of the first for prefetching.
68+
* node->prefetch_pages tracks exactly how many pages ahead the prefetch
69+
* iterator is. Also, node->prefetch_target tracks the desired prefetch
70+
* distance, which starts small and increases up to the
71+
* node->prefetch_maximum. This is to avoid doing a lot of prefetching in a
72+
* scan that stops after a few tuples because of a LIMIT.
73+
*/
74+
static void
75+
BitmapTableScanSetup(BitmapHeapScanState *node)
76+
{
77+
TBMIterator tbmiterator = {0};
78+
ParallelBitmapHeapState *pstate = node->pstate;
79+
dsa_area *dsa = node->ss.ps.state->es_query_dsa;
80+
81+
if (!pstate)
82+
{
83+
node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
84+
85+
if (!node->tbm || !IsA(node->tbm, TIDBitmap))
86+
elog(ERROR, "unrecognized result from subplan");
87+
}
88+
else if (BitmapShouldInitializeSharedState(pstate))
89+
{
90+
/*
91+
* The leader will immediately come out of the function, but others
92+
* will be blocked until leader populates the TBM and wakes them up.
93+
*/
94+
node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
95+
if (!node->tbm || !IsA(node->tbm, TIDBitmap))
96+
elog(ERROR, "unrecognized result from subplan");
97+
98+
/*
99+
* Prepare to iterate over the TBM. This will return the dsa_pointer
100+
* of the iterator state which will be used by multiple processes to
101+
* iterate jointly.
102+
*/
103+
pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
104+
105+
#ifdef USE_PREFETCH
106+
if (node->prefetch_maximum > 0)
107+
{
108+
pstate->prefetch_iterator =
109+
tbm_prepare_shared_iterate(node->tbm);
110+
}
111+
#endif /* USE_PREFETCH */
112+
113+
/* We have initialized the shared state so wake up others. */
114+
BitmapDoneInitializingSharedState(pstate);
115+
}
116+
117+
tbmiterator = tbm_begin_iterate(node->tbm, dsa,
118+
pstate ?
119+
pstate->tbmiterator :
120+
InvalidDsaPointer);
121+
122+
#ifdef USE_PREFETCH
123+
if (node->prefetch_maximum > 0)
124+
node->prefetch_iterator =
125+
tbm_begin_iterate(node->tbm, dsa,
126+
pstate ?
127+
pstate->prefetch_iterator :
128+
InvalidDsaPointer);
129+
#endif /* USE_PREFETCH */
130+
131+
/*
132+
* If this is the first scan of the underlying table, create the table
133+
* scan descriptor and begin the scan.
134+
*/
135+
if (!node->ss.ss_currentScanDesc)
136+
{
137+
bool need_tuples = false;
138+
139+
/*
140+
* We can potentially skip fetching heap pages if we do not need any
141+
* columns of the table, either for checking non-indexable quals or
142+
* for returning data. This test is a bit simplistic, as it checks
143+
* the stronger condition that there's no qual or return tlist at all.
144+
* But in most cases it's probably not worth working harder than that.
145+
*/
146+
need_tuples = (node->ss.ps.plan->qual != NIL ||
147+
node->ss.ps.plan->targetlist != NIL);
148+
149+
node->ss.ss_currentScanDesc =
150+
table_beginscan_bm(node->ss.ss_currentRelation,
151+
node->ss.ps.state->es_snapshot,
152+
0,
153+
NULL,
154+
need_tuples);
155+
}
156+
157+
node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
158+
node->initialized = true;
159+
}
160+
161+
60162
/* ----------------------------------------------------------------
61163
* BitmapHeapNext
62164
*
@@ -68,121 +170,27 @@ BitmapHeapNext(BitmapHeapScanState *node)
68170
{
69171
ExprContext *econtext;
70172
TableScanDesc scan;
71-
TIDBitmap *tbm;
72173
TupleTableSlot *slot;
174+
175+
#ifdef USE_PREFETCH
73176
ParallelBitmapHeapState *pstate = node->pstate;
74-
dsa_area *dsa = node->ss.ps.state->es_query_dsa;
177+
#endif
75178

76179
/*
77180
* extract necessary information from index scan node
78181
*/
79182
econtext = node->ss.ps.ps_ExprContext;
80183
slot = node->ss.ss_ScanTupleSlot;
81184
scan = node->ss.ss_currentScanDesc;
82-
tbm = node->tbm;
83185

84186
/*
85187
* If we haven't yet performed the underlying index scan, do it, and begin
86188
* the iteration over the bitmap.
87-
*
88-
* For prefetching, we use *two* iterators, one for the pages we are
89-
* actually scanning and another that runs ahead of the first for
90-
* prefetching. node->prefetch_pages tracks exactly how many pages ahead
91-
* the prefetch iterator is. Also, node->prefetch_target tracks the
92-
* desired prefetch distance, which starts small and increases up to the
93-
* node->prefetch_maximum. This is to avoid doing a lot of prefetching in
94-
* a scan that stops after a few tuples because of a LIMIT.
95189
*/
96190
if (!node->initialized)
97191
{
98-
TBMIterator tbmiterator;
99-
100-
if (!pstate)
101-
{
102-
tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
103-
104-
if (!tbm || !IsA(tbm, TIDBitmap))
105-
elog(ERROR, "unrecognized result from subplan");
106-
107-
node->tbm = tbm;
108-
}
109-
else if (BitmapShouldInitializeSharedState(pstate))
110-
{
111-
/*
112-
* The leader will immediately come out of the function, but
113-
* others will be blocked until leader populates the TBM and wakes
114-
* them up.
115-
*/
116-
tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
117-
if (!tbm || !IsA(tbm, TIDBitmap))
118-
elog(ERROR, "unrecognized result from subplan");
119-
120-
node->tbm = tbm;
121-
122-
/*
123-
* Prepare to iterate over the TBM. This will return the
124-
* dsa_pointer of the iterator state which will be used by
125-
* multiple processes to iterate jointly.
126-
*/
127-
pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
128-
129-
#ifdef USE_PREFETCH
130-
if (node->prefetch_maximum > 0)
131-
{
132-
pstate->prefetch_iterator =
133-
tbm_prepare_shared_iterate(tbm);
134-
}
135-
#endif /* USE_PREFETCH */
136-
137-
/* We have initialized the shared state so wake up others. */
138-
BitmapDoneInitializingSharedState(pstate);
139-
}
140-
141-
tbmiterator = tbm_begin_iterate(tbm, dsa,
142-
pstate ?
143-
pstate->tbmiterator :
144-
InvalidDsaPointer);
145-
146-
#ifdef USE_PREFETCH
147-
if (node->prefetch_maximum > 0)
148-
node->prefetch_iterator =
149-
tbm_begin_iterate(tbm, dsa,
150-
pstate ?
151-
pstate->prefetch_iterator :
152-
InvalidDsaPointer);
153-
#endif /* USE_PREFETCH */
154-
155-
/*
156-
* If this is the first scan of the underlying table, create the table
157-
* scan descriptor and begin the scan.
158-
*/
159-
if (!scan)
160-
{
161-
bool need_tuples = false;
162-
163-
/*
164-
* We can potentially skip fetching heap pages if we do not need
165-
* any columns of the table, either for checking non-indexable
166-
* quals or for returning data. This test is a bit simplistic, as
167-
* it checks the stronger condition that there's no qual or return
168-
* tlist at all. But in most cases it's probably not worth working
169-
* harder than that.
170-
*/
171-
need_tuples = (node->ss.ps.plan->qual != NIL ||
172-
node->ss.ps.plan->targetlist != NIL);
173-
174-
scan = table_beginscan_bm(node->ss.ss_currentRelation,
175-
node->ss.ps.state->es_snapshot,
176-
0,
177-
NULL,
178-
need_tuples);
179-
180-
node->ss.ss_currentScanDesc = scan;
181-
}
182-
183-
scan->st.rs_tbmiterator = tbmiterator;
184-
node->initialized = true;
185-
192+
BitmapTableScanSetup(node);
193+
scan = node->ss.ss_currentScanDesc;
186194
goto new_page;
187195
}
188196

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy