summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorMelanie Plageman2025-02-24 21:07:55 +0000
committerMelanie Plageman2025-02-24 21:10:19 +0000
commitbfe56cdf9a4e07edca46254a88efd9ef17421cd7 (patch)
tree8873b768c437042a67730df2da4cd3138e0ece00 /src/backend/access
parentb8778c4cd8bc924ce5347cb1ab10dfbf34130559 (diff)
Delay extraction of TIDBitmap per page offsets
Pages from the bitmap created by the TIDBitmap API can be exact or lossy. The TIDBitmap API extracts the tuple offsets from exact pages into an array for the convenience of the caller. This was done in tbm_private|shared_iterate() right after advancing the iterator. However, as long as tbm_private|shared_iterate() set a reference to the PagetableEntry in the TBMIterateResult, the offset extraction can be done later. Waiting to extract the tuple offsets has a few benefits. For the shared iterator case, it allows us to extract the offsets after dropping the shared iterator state lock, reducing time spent holding a contended lock. Separating the iteration step and extracting the offsets later also allows us to avoid extracting the offsets for prefetched blocks. Those offsets were never used, so the overhead of extracting and storing them was wasted. The real motivation for this change, however, is that future commits will make bitmap heap scan use the read stream API. This requires a TBMIterateResult per issued block. By removing the array of tuple offsets from the TBMIterateResult and only extracting the offsets when they are used, we reduce the memory required for per buffer data substantially. Suggested-by: Thomas Munro <thomas.munro@gmail.com> Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGLHbKP3jwJ6_%2BhnGi37Pw3BD5j2amjV3oSk7j-KyCnY7Q%40mail.gmail.com
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/gin/ginget.c28
-rw-r--r--src/backend/access/gin/ginscan.c1
-rw-r--r--src/backend/access/heap/heapam_handler.c17
3 files changed, 34 insertions, 12 deletions
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 54aecc1d1f1..f3b19d280c3 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -333,6 +333,7 @@ restartScanEntry:
entry->nlist = 0;
entry->matchBitmap = NULL;
entry->matchResult = NULL;
+ entry->matchNtuples = -1;
entry->reduceResult = false;
entry->predictNumberResult = 0;
@@ -828,7 +829,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
*/
while (entry->matchResult == NULL ||
(!entry->matchResult->lossy &&
- entry->offset >= entry->matchResult->ntuples) ||
+ entry->offset >= entry->matchNtuples) ||
entry->matchResult->blockno < advancePastBlk ||
(ItemPointerIsLossyPage(&advancePast) &&
entry->matchResult->blockno == advancePastBlk))
@@ -845,9 +846,15 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
break;
}
+ /* Exact pages need their tuple offsets extracted. */
+ if (!entry->matchResult->lossy)
+ entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
+ entry->matchOffsets,
+ TBM_MAX_TUPLES_PER_PAGE);
+
/*
* Reset counter to the beginning of entry->matchResult. Note:
- * entry->offset is still greater than matchResult->ntuples if
+ * entry->offset is still greater than entry->matchNtuples if
* matchResult is lossy. So, on next call we will get next
* result from TIDBitmap.
*/
@@ -874,32 +881,35 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
}
/*
- * Not a lossy page. Skip over any offsets <= advancePast, and
- * return that.
+ * Not a lossy page. If tuple offsets were extracted,
+ * entry->matchNtuples must be > -1
*/
+ Assert(entry->matchNtuples > -1);
+
+ /* Skip over any offsets <= advancePast, and return that. */
if (entry->matchResult->blockno == advancePastBlk)
{
- Assert(entry->matchResult->ntuples > 0);
+ Assert(entry->matchNtuples > 0);
/*
* First, do a quick check against the last offset on the
* page. If that's > advancePast, so are all the other
* offsets, so just go back to the top to get the next page.
*/
- if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
+ if (entry->matchOffsets[entry->matchNtuples - 1] <= advancePastOff)
{
- entry->offset = entry->matchResult->ntuples;
+ entry->offset = entry->matchNtuples;
continue;
}
/* Otherwise scan to find the first item > advancePast */
- while (entry->matchResult->offsets[entry->offset] <= advancePastOff)
+ while (entry->matchOffsets[entry->offset] <= advancePastOff)
entry->offset++;
}
ItemPointerSet(&entry->curItem,
entry->matchResult->blockno,
- entry->matchResult->offsets[entry->offset]);
+ entry->matchOffsets[entry->offset]);
entry->offset++;
/* Done unless we need to reduce the result */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 7d1e6615260..63ded6301e2 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -107,6 +107,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
scanEntry->matchBitmap = NULL;
scanEntry->matchIterator = NULL;
scanEntry->matchResult = NULL;
+ scanEntry->matchNtuples = -1;
scanEntry->list = NULL;
scanEntry->nlist = 0;
scanEntry->offset = InvalidOffsetNumber;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 269d581c2ec..e78682c3cef 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2127,6 +2127,8 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
Snapshot snapshot;
int ntup;
TBMIterateResult *tbmres;
+ OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
+ int noffsets = -1;
Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN);
@@ -2145,6 +2147,11 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
if (tbmres == NULL)
return false;
+ /* Exact pages need their tuple offsets extracted. */
+ if (!tbmres->lossy)
+ noffsets = tbm_extract_page_tuple(tbmres, offsets,
+ TBM_MAX_TUPLES_PER_PAGE);
+
/*
* Ignore any claimed entries past what we think is the end of the
* relation. It may have been extended after the start of our scan (we
@@ -2172,8 +2179,9 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
/* can't be lossy in the skip_fetch case */
Assert(!tbmres->lossy);
Assert(bscan->rs_empty_tuples_pending >= 0);
+ Assert(noffsets > -1);
- bscan->rs_empty_tuples_pending += tbmres->ntuples;
+ bscan->rs_empty_tuples_pending += noffsets;
return true;
}
@@ -2216,9 +2224,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
*/
int curslot;
- for (curslot = 0; curslot < tbmres->ntuples; curslot++)
+ /* We must have extracted the tuple offsets by now */
+ Assert(noffsets > -1);
+
+ for (curslot = 0; curslot < noffsets; curslot++)
{
- OffsetNumber offnum = tbmres->offsets[curslot];
+ OffsetNumber offnum = offsets[curslot];
ItemPointerData tid;
HeapTupleData heapTuple;