Skip to content

Commit 942e8e2

Browse files
author
Commitfest Bot
committed
[CF 4874] v36 - BitmapHeapScan table AM violation removal (and use streaming read API)
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/4874 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAAKRu_b8nJua_W_C1i46a-XaMzJJnYF+8BpET0zyoREXEvrmhQ@mail.gmail.com Author(s): Melanie Plageman
2 parents 4618045 + 08cba16 commit 942e8e2

File tree

16 files changed

+826
-911
lines changed

16 files changed

+826
-911
lines changed

src/backend/access/gin/ginget.c

+16-17
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot)
332332
entry->list = NULL;
333333
entry->nlist = 0;
334334
entry->matchBitmap = NULL;
335-
entry->matchResult = NULL;
336335
entry->matchNtuples = -1;
336+
entry->matchResult.blockno = InvalidBlockNumber;
337337
entry->reduceResult = false;
338338
entry->predictNumberResult = 0;
339339

@@ -827,20 +827,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
827827
{
828828
/*
829829
* If we've exhausted all items on this block, move to next block
830-
* in the bitmap.
830+
* in the bitmap. tbm_private_iterate() sets matchResult.blockno
831+
* to InvalidBlockNumber when the bitmap is exhausted.
831832
*/
832-
while (entry->matchResult == NULL ||
833-
(!entry->matchResult->lossy &&
833+
while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
834+
(!entry->matchResult.lossy &&
834835
entry->offset >= entry->matchNtuples) ||
835-
entry->matchResult->blockno < advancePastBlk ||
836+
entry->matchResult.blockno < advancePastBlk ||
836837
(ItemPointerIsLossyPage(&advancePast) &&
837-
entry->matchResult->blockno == advancePastBlk))
838+
entry->matchResult.blockno == advancePastBlk))
838839
{
839-
entry->matchResult =
840-
tbm_private_iterate(entry->matchIterator);
841-
842-
if (entry->matchResult == NULL)
840+
if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
843841
{
842+
Assert(!BlockNumberIsValid(entry->matchResult.blockno));
844843
ItemPointerSetInvalid(&entry->curItem);
845844
tbm_end_private_iterate(entry->matchIterator);
846845
entry->matchIterator = NULL;
@@ -849,14 +848,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
849848
}
850849

851850
/* Exact pages need their tuple offsets extracted. */
852-
if (!entry->matchResult->lossy)
853-
entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
851+
if (!entry->matchResult.lossy)
852+
entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
854853
entry->matchOffsets,
855854
TBM_MAX_TUPLES_PER_PAGE);
856855

857856
/*
858857
* Reset counter to the beginning of entry->matchResult. Note:
859-
* entry->offset is still greater than entry->matchNtuples if
858+
* entry->offset is still greater than matchResult.ntuples if
860859
* matchResult is lossy. So, on next call we will get next
861860
* result from TIDBitmap.
862861
*/
@@ -869,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
869868
* We're now on the first page after advancePast which has any
870869
* items on it. If it's a lossy result, return that.
871870
*/
872-
if (entry->matchResult->lossy)
871+
if (entry->matchResult.lossy)
873872
{
874873
ItemPointerSetLossyPage(&entry->curItem,
875-
entry->matchResult->blockno);
874+
entry->matchResult.blockno);
876875

877876
/*
878877
* We might as well fall out of the loop; we could not
@@ -889,7 +888,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
889888
Assert(entry->matchNtuples > -1);
890889

891890
/* Skip over any offsets <= advancePast, and return that. */
892-
if (entry->matchResult->blockno == advancePastBlk)
891+
if (entry->matchResult.blockno == advancePastBlk)
893892
{
894893
Assert(entry->matchNtuples > 0);
895894

@@ -910,7 +909,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
910909
}
911910

912911
ItemPointerSet(&entry->curItem,
913-
entry->matchResult->blockno,
912+
entry->matchResult.blockno,
914913
entry->matchOffsets[entry->offset]);
915914
entry->offset++;
916915

src/backend/access/gin/ginscan.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
111111
ItemPointerSetMin(&scanEntry->curItem);
112112
scanEntry->matchBitmap = NULL;
113113
scanEntry->matchIterator = NULL;
114-
scanEntry->matchResult = NULL;
114+
scanEntry->matchResult.blockno = InvalidBlockNumber;
115115
scanEntry->matchNtuples = -1;
116116
scanEntry->list = NULL;
117117
scanEntry->nlist = 0;

src/backend/access/heap/heapam.c

+80
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,72 @@ heap_scan_stream_read_next_serial(ReadStream *stream,
279279
return scan->rs_prefetch_block;
280280
}
281281

282+
/*
283+
* Read stream API callback for bitmap heap scans.
284+
* Returns the next block the caller wants from the read stream or
285+
* InvalidBlockNumber when done.
286+
*/
287+
static BlockNumber
288+
bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
289+
void *per_buffer_data)
290+
{
291+
TBMIterateResult *tbmres = per_buffer_data;
292+
BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data;
293+
HeapScanDesc hscan = (HeapScanDesc) bscan;
294+
TableScanDesc sscan = &hscan->rs_base;
295+
296+
for (;;)
297+
{
298+
CHECK_FOR_INTERRUPTS();
299+
300+
/* no more entries in the bitmap */
301+
if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres))
302+
return InvalidBlockNumber;
303+
304+
/*
305+
* Ignore any claimed entries past what we think is the end of the
306+
* relation. It may have been extended after the start of our scan (we
307+
* only hold an AccessShareLock, and it could be inserts from this
308+
* backend). We don't take this optimization in SERIALIZABLE
309+
* isolation though, as we need to examine all invisible tuples
310+
* reachable by the index.
311+
*/
312+
if (!IsolationIsSerializable() &&
313+
tbmres->blockno >= hscan->rs_nblocks)
314+
continue;
315+
316+
/*
317+
* We can skip fetching the heap page if we don't need any fields from
318+
* the heap, the bitmap entries don't need rechecking, and all tuples
319+
* on the page are visible to our transaction.
320+
*/
321+
if (!(sscan->rs_flags & SO_NEED_TUPLES) &&
322+
!tbmres->recheck &&
323+
VM_ALL_VISIBLE(sscan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
324+
{
325+
OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
326+
int noffsets;
327+
328+
/* can't be lossy in the skip_fetch case */
329+
Assert(!tbmres->lossy);
330+
Assert(bscan->rs_empty_tuples_pending >= 0);
331+
332+
/*
333+
* We throw away the offsets, but this is the easiest way to get a
334+
* count of tuples.
335+
*/
336+
noffsets = tbm_extract_page_tuple(tbmres, offsets, TBM_MAX_TUPLES_PER_PAGE);
337+
bscan->rs_empty_tuples_pending += noffsets;
338+
continue;
339+
}
340+
341+
return tbmres->blockno;
342+
}
343+
344+
/* not reachable */
345+
Assert(false);
346+
}
347+
282348
/* ----------------
283349
* initscan - scan code common to heap_beginscan and heap_rescan
284350
* ----------------
@@ -1067,6 +1133,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
10671133
scan->rs_base.rs_flags = flags;
10681134
scan->rs_base.rs_parallel = parallel_scan;
10691135
scan->rs_strategy = NULL; /* set in initscan */
1136+
scan->rs_cbuf = InvalidBuffer;
10701137

10711138
/*
10721139
* Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1146,6 +1213,16 @@ heap_beginscan(Relation relation, Snapshot snapshot,
11461213
scan,
11471214
0);
11481215
}
1216+
else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
1217+
{
1218+
scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT,
1219+
scan->rs_strategy,
1220+
scan->rs_base.rs_rd,
1221+
MAIN_FORKNUM,
1222+
bitmapheap_stream_read_next,
1223+
scan,
1224+
sizeof(TBMIterateResult));
1225+
}
11491226

11501227

11511228
return (TableScanDesc) scan;
@@ -1180,7 +1257,10 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
11801257
* unpin scan buffers
11811258
*/
11821259
if (BufferIsValid(scan->rs_cbuf))
1260+
{
11831261
ReleaseBuffer(scan->rs_cbuf);
1262+
scan->rs_cbuf = InvalidBuffer;
1263+
}
11841264

11851265
if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
11861266
{

0 commit comments

Comments
 (0)