Skip to content

Commit 1a0da34

Browse files
Bitmap Table Scans use unified TBMIterator
With the repurposing of TBMIterator as an interface for both parallel and serial iteration through TIDBitmaps in commit 7f9d418, 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
1 parent 7f9d418 commit 1a0da34

File tree

6 files changed

+86
-123
lines changed

6 files changed

+86
-123
lines changed

src/backend/access/heap/heapam_handler.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -2135,10 +2135,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21352135
{
21362136
CHECK_FOR_INTERRUPTS();
21372137

2138-
if (scan->st.bitmap.rs_shared_iterator)
2139-
tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
2140-
else
2141-
tbmres = tbm_private_iterate(scan->st.bitmap.rs_iterator);
2138+
tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
21422139

21432140
if (tbmres == NULL)
21442141
return false;

src/backend/executor/nodeBitmapHeapscan.c

+69-101
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
9595
*/
9696
if (!node->initialized)
9797
{
98-
TBMPrivateIterator *tbmiterator = NULL;
99-
TBMSharedIterator *shared_tbmiterator = NULL;
98+
TBMIterator tbmiterator;
10099

101100
if (!pstate)
102101
{
@@ -106,70 +105,62 @@ BitmapHeapNext(BitmapHeapScanState *node)
106105
elog(ERROR, "unrecognized result from subplan");
107106

108107
node->tbm = tbm;
109-
tbmiterator = tbm_begin_private_iterate(tbm);
110108

111109
#ifdef USE_PREFETCH
112110
if (node->prefetch_maximum > 0)
113-
{
114-
node->prefetch_iterator = tbm_begin_private_iterate(tbm);
115-
node->prefetch_pages = 0;
116-
node->prefetch_target = -1;
117-
}
111+
node->prefetch_iterator =
112+
tbm_begin_iterate(node->tbm, dsa,
113+
pstate ?
114+
pstate->prefetch_iterator :
115+
InvalidDsaPointer);
118116
#endif /* USE_PREFETCH */
119117
}
120-
else
118+
else if (BitmapShouldInitializeSharedState(pstate))
121119
{
122120
/*
123121
* The leader will immediately come out of the function, but
124122
* others will be blocked until leader populates the TBM and wakes
125123
* them up.
126124
*/
127-
if (BitmapShouldInitializeSharedState(pstate))
128-
{
129-
tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
130-
if (!tbm || !IsA(tbm, TIDBitmap))
131-
elog(ERROR, "unrecognized result from subplan");
132-
133-
node->tbm = tbm;
134-
135-
/*
136-
* Prepare to iterate over the TBM. This will return the
137-
* dsa_pointer of the iterator state which will be used by
138-
* multiple processes to iterate jointly.
139-
*/
140-
pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
141-
#ifdef USE_PREFETCH
142-
if (node->prefetch_maximum > 0)
143-
{
144-
pstate->prefetch_iterator =
145-
tbm_prepare_shared_iterate(tbm);
146-
147-
/*
148-
* We don't need the mutex here as we haven't yet woke up
149-
* others.
150-
*/
151-
pstate->prefetch_pages = 0;
152-
pstate->prefetch_target = -1;
153-
}
154-
#endif
125+
tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
126+
if (!tbm || !IsA(tbm, TIDBitmap))
127+
elog(ERROR, "unrecognized result from subplan");
155128

156-
/* We have initialized the shared state so wake up others. */
157-
BitmapDoneInitializingSharedState(pstate);
158-
}
129+
node->tbm = tbm;
159130

160-
/* Allocate a private iterator and attach the shared state to it */
161-
shared_tbmiterator =
162-
tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
131+
/*
132+
* Prepare to iterate over the TBM. This will return the
133+
* dsa_pointer of the iterator state which will be used by
134+
* multiple processes to iterate jointly.
135+
*/
136+
pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
163137

164138
#ifdef USE_PREFETCH
165139
if (node->prefetch_maximum > 0)
166140
{
167-
node->shared_prefetch_iterator =
168-
tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
141+
pstate->prefetch_iterator =
142+
tbm_prepare_shared_iterate(tbm);
169143
}
170144
#endif /* USE_PREFETCH */
145+
146+
/* We have initialized the shared state so wake up others. */
147+
BitmapDoneInitializingSharedState(pstate);
171148
}
172149

150+
tbmiterator = tbm_begin_iterate(tbm, dsa,
151+
pstate ?
152+
pstate->tbmiterator :
153+
InvalidDsaPointer);
154+
155+
#ifdef USE_PREFETCH
156+
if (node->prefetch_maximum > 0)
157+
node->prefetch_iterator =
158+
tbm_begin_iterate(tbm, dsa,
159+
pstate ?
160+
pstate->prefetch_iterator :
161+
InvalidDsaPointer);
162+
#endif /* USE_PREFETCH */
163+
173164
/*
174165
* If this is the first scan of the underlying table, create the table
175166
* scan descriptor and begin the scan.
@@ -198,8 +189,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
198189
node->ss.ss_currentScanDesc = scan;
199190
}
200191

201-
scan->st.bitmap.rs_iterator = tbmiterator;
202-
scan->st.bitmap.rs_shared_iterator = shared_tbmiterator;
192+
scan->st.rs_tbmiterator = tbmiterator;
203193
node->initialized = true;
204194

205195
goto new_page;
@@ -285,7 +275,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
285275
* ahead of the current block.
286276
*/
287277
if (node->pstate == NULL &&
288-
node->prefetch_iterator &&
278+
!tbm_exhausted(&node->prefetch_iterator) &&
289279
node->prefetch_blockno < node->blockno)
290280
elog(ERROR,
291281
"prefetch and main iterators are out of sync. pfblockno: %d. blockno: %d",
@@ -332,16 +322,16 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
332322

333323
if (pstate == NULL)
334324
{
335-
TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
325+
TBMIterator *prefetch_iterator = &node->prefetch_iterator;
336326

337327
if (node->prefetch_pages > 0)
338328
{
339329
/* The main iterator has closed the distance by one page */
340330
node->prefetch_pages--;
341331
}
342-
else if (prefetch_iterator)
332+
else if (!tbm_exhausted(prefetch_iterator))
343333
{
344-
tbmpre = tbm_private_iterate(prefetch_iterator);
334+
tbmpre = tbm_iterate(prefetch_iterator);
345335
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
346336
InvalidBlockNumber;
347337
}
@@ -359,7 +349,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
359349
*/
360350
if (node->prefetch_maximum > 0)
361351
{
362-
TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
352+
TBMIterator *prefetch_iterator = &node->prefetch_iterator;
363353

364354
SpinLockAcquire(&pstate->mutex);
365355
if (pstate->prefetch_pages > 0)
@@ -380,9 +370,9 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
380370
* we don't validate the blockno here as we do in non-parallel
381371
* case.
382372
*/
383-
if (prefetch_iterator)
373+
if (!tbm_exhausted(prefetch_iterator))
384374
{
385-
tbmpre = tbm_shared_iterate(prefetch_iterator);
375+
tbmpre = tbm_iterate(prefetch_iterator);
386376
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
387377
InvalidBlockNumber;
388378
}
@@ -446,21 +436,19 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
446436

447437
if (pstate == NULL)
448438
{
449-
TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
439+
TBMIterator *prefetch_iterator = &node->prefetch_iterator;
450440

451-
if (prefetch_iterator)
441+
if (!tbm_exhausted(prefetch_iterator))
452442
{
453443
while (node->prefetch_pages < node->prefetch_target)
454444
{
455-
TBMIterateResult *tbmpre;
445+
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
456446
bool skip_fetch;
457447

458-
tbmpre = tbm_private_iterate(prefetch_iterator);
459448
if (tbmpre == NULL)
460449
{
461450
/* No more pages to prefetch */
462-
tbm_end_private_iterate(prefetch_iterator);
463-
node->prefetch_iterator = NULL;
451+
tbm_end_iterate(prefetch_iterator);
464452
break;
465453
}
466454
node->prefetch_pages++;
@@ -488,9 +476,9 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
488476

489477
if (pstate->prefetch_pages < pstate->prefetch_target)
490478
{
491-
TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
479+
TBMIterator *prefetch_iterator = &node->prefetch_iterator;
492480

493-
if (prefetch_iterator)
481+
if (!tbm_exhausted(prefetch_iterator))
494482
{
495483
while (1)
496484
{
@@ -513,12 +501,11 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
513501
if (!do_prefetch)
514502
return;
515503

516-
tbmpre = tbm_shared_iterate(prefetch_iterator);
504+
tbmpre = tbm_iterate(prefetch_iterator);
517505
if (tbmpre == NULL)
518506
{
519507
/* No more pages to prefetch */
520-
tbm_end_shared_iterate(prefetch_iterator);
521-
node->shared_prefetch_iterator = NULL;
508+
tbm_end_iterate(prefetch_iterator);
522509
break;
523510
}
524511

@@ -587,39 +574,30 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
587574
/*
588575
* End iteration on iterators saved in scan descriptor.
589576
*/
590-
if (scan->st.bitmap.rs_shared_iterator)
591-
{
592-
tbm_end_shared_iterate(scan->st.bitmap.rs_shared_iterator);
593-
scan->st.bitmap.rs_shared_iterator = NULL;
594-
}
595-
596-
if (scan->st.bitmap.rs_iterator)
597-
{
598-
tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
599-
scan->st.bitmap.rs_iterator = NULL;
600-
}
577+
tbm_end_iterate(&scan->st.rs_tbmiterator);
601578

602579
/* rescan to release any page pin */
603580
table_rescan(node->ss.ss_currentScanDesc, NULL);
604581
}
605582

583+
/* If we did not already clean up the prefetch iterator, do so now. */
584+
if (!tbm_exhausted(&node->prefetch_iterator))
585+
tbm_end_iterate(&node->prefetch_iterator);
586+
606587
/* release bitmaps and buffers if any */
607-
if (node->prefetch_iterator)
608-
tbm_end_private_iterate(node->prefetch_iterator);
609-
if (node->shared_prefetch_iterator)
610-
tbm_end_shared_iterate(node->shared_prefetch_iterator);
611588
if (node->tbm)
612589
tbm_free(node->tbm);
613590
if (node->pvmbuffer != InvalidBuffer)
614591
ReleaseBuffer(node->pvmbuffer);
615592
node->tbm = NULL;
616-
node->prefetch_iterator = NULL;
617593
node->initialized = false;
618-
node->shared_prefetch_iterator = NULL;
619594
node->pvmbuffer = InvalidBuffer;
620595
node->recheck = true;
596+
/* Only used for serial BHS */
621597
node->blockno = InvalidBlockNumber;
622598
node->prefetch_blockno = InvalidBlockNumber;
599+
node->prefetch_pages = 0;
600+
node->prefetch_target = -1;
623601

624602
ExecScanReScan(&node->ss);
625603

@@ -678,33 +656,23 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
678656
/*
679657
* End iteration on iterators saved in scan descriptor.
680658
*/
681-
if (scanDesc->st.bitmap.rs_shared_iterator)
682-
{
683-
tbm_end_shared_iterate(scanDesc->st.bitmap.rs_shared_iterator);
684-
scanDesc->st.bitmap.rs_shared_iterator = NULL;
685-
}
686-
687-
if (scanDesc->st.bitmap.rs_iterator)
688-
{
689-
tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
690-
scanDesc->st.bitmap.rs_iterator = NULL;
691-
}
659+
tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
692660

693661
/*
694662
* close table scan
695663
*/
696664
table_endscan(scanDesc);
697665
}
698666

667+
/* If we did not already clean up the prefetch iterator, do so now. */
668+
if (!tbm_exhausted(&node->prefetch_iterator))
669+
tbm_end_iterate(&node->prefetch_iterator);
670+
699671
/*
700672
* release bitmaps and buffers if any
701673
*/
702-
if (node->prefetch_iterator)
703-
tbm_end_private_iterate(node->prefetch_iterator);
704674
if (node->tbm)
705675
tbm_free(node->tbm);
706-
if (node->shared_prefetch_iterator)
707-
tbm_end_shared_iterate(node->shared_prefetch_iterator);
708676
if (node->pvmbuffer != InvalidBuffer)
709677
ReleaseBuffer(node->pvmbuffer);
710678
}
@@ -744,11 +712,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
744712
/* Zero the statistics counters */
745713
memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
746714

747-
scanstate->prefetch_iterator = NULL;
748715
scanstate->prefetch_pages = 0;
749-
scanstate->prefetch_target = 0;
716+
scanstate->prefetch_target = -1;
750717
scanstate->initialized = false;
751-
scanstate->shared_prefetch_iterator = NULL;
752718
scanstate->pstate = NULL;
753719
scanstate->recheck = true;
754720
scanstate->blockno = InvalidBlockNumber;
@@ -907,7 +873,7 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
907873
/* Initialize the mutex */
908874
SpinLockInit(&pstate->mutex);
909875
pstate->prefetch_pages = 0;
910-
pstate->prefetch_target = 0;
876+
pstate->prefetch_target = -1;
911877
pstate->state = BM_INITIAL;
912878

913879
ConditionVariableInit(&pstate->cv);
@@ -944,6 +910,8 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
944910
return;
945911

946912
pstate->state = BM_INITIAL;
913+
pstate->prefetch_pages = 0;
914+
pstate->prefetch_target = -1;
947915

948916
if (DsaPointerIsValid(pstate->tbmiterator))
949917
tbm_free_shared_area(dsa, pstate->tbmiterator);

src/include/access/relscan.h

+3-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "access/htup_details.h"
1818
#include "access/itup.h"
19+
#include "nodes/tidbitmap.h"
1920
#include "port/atomics.h"
2021
#include "storage/buf.h"
2122
#include "storage/relfilelocator.h"
@@ -25,9 +26,6 @@
2526

2627
struct ParallelTableScanDescData;
2728

28-
struct TBMPrivateIterator;
29-
struct TBMSharedIterator;
30-
3129
/*
3230
* Generic descriptor for table scans. This is the base-class for table scans,
3331
* which needs to be embedded in the scans of individual AMs.
@@ -45,12 +43,8 @@ typedef struct TableScanDescData
4543
*/
4644
union
4745
{
48-
/* Iterators for Bitmap Table Scans */
49-
struct
50-
{
51-
struct TBMPrivateIterator *rs_iterator;
52-
struct TBMSharedIterator *rs_shared_iterator;
53-
} bitmap;
46+
/* Iterator for Bitmap Table Scans */
47+
TBMIterator rs_tbmiterator;
5448

5549
/*
5650
* Range of ItemPointers for table_scan_getnextslot_tidrange() to

0 commit comments

Comments
 (0)