v16-0002-heapam-Track-heap-block-in-IndexFetchHeapData-us.patch
application/octet-stream
Filename: v16-0002-heapam-Track-heap-block-in-IndexFetchHeapData-us.patch
Type: application/octet-stream
Part: 16
Message:
Re: index prefetching
Patch
Format: format-patch
Series: patch v16-0002
Subject: heapam: Track heap block in IndexFetchHeapData using xs_blk
| File | + | − |
|---|---|---|
| src/backend/access/heap/heapam_handler.c | 18 | 11 |
| src/include/access/heapam.h | 3 | 2 |
From 997822891f393a13be22c1be2d2d0094a485fddf Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Tue, 10 Mar 2026 14:40:35 -0400
Subject: [PATCH v16 02/17] heapam: Track heap block in IndexFetchHeapData
using xs_blk
Add an explicit BlockNumber field (xs_blk) to IndexFetchHeapData that
tracks which heap block is currently pinned in xs_cbuf.
heapam_index_fetch_tuple now uses xs_blk to determine when buffer
switching is needed, replacing the previous approach that compared
buffer identities via ReleaseAndReadBuffer on every non-HOT-chain call.
The new approach skips the buffer-switching path entirely when the next
TID is on the same heap page, which also means that heap_page_prune_opt
is called exactly once per block (when the block is first pinned).
This is preparatory work for an upcoming commit that will need xs_blk
to manage buffer pin transfers between the scan and the executor slot.
---
src/include/access/heapam.h | 5 ++--
src/backend/access/heap/heapam_handler.c | 29 +++++++++++++++---------
2 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2fdc50b86..9bcf74862 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -123,10 +123,11 @@ typedef struct IndexFetchHeapData
IndexFetchTableData xs_base; /* AM independent part of the descriptor */
/*
- * Current heap buffer in scan, if any. NB: if xs_cbuf is not
- * InvalidBuffer, we hold a pin on that buffer.
+ * Current heap buffer in scan (and its block number), if any. NB: if
+ * xs_blk is not InvalidBlockNumber, we hold a pin in xs_cbuf.
*/
Buffer xs_cbuf;
+ BlockNumber xs_blk;
/* Current heap block's corresponding page in the visibility map */
Buffer xs_vmbuffer;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 253a735b6..cfe4689a8 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -86,6 +86,7 @@ heapam_index_fetch_begin(Relation rel)
hscan->xs_base.rel = rel;
hscan->xs_cbuf = InvalidBuffer;
+ hscan->xs_blk = InvalidBlockNumber;
hscan->xs_vmbuffer = InvalidBuffer;
return &hscan->xs_base;
@@ -107,6 +108,7 @@ heapam_index_fetch_reset(IndexFetchTableData *scan)
ReleaseBuffer(hscan->xs_vmbuffer);
hscan->xs_vmbuffer = InvalidBuffer;
}
+ hscan->xs_blk = InvalidBlockNumber;
}
static void
@@ -132,24 +134,29 @@ heapam_index_fetch_tuple(struct IndexFetchTableData *scan,
Assert(TTS_IS_BUFFERTUPLE(slot));
- /* We can skip the buffer-switching logic if we're in mid-HOT chain. */
- if (!*call_again)
+ /* We can skip the buffer-switching logic if we're on the same page. */
+ if (hscan->xs_blk != ItemPointerGetBlockNumber(tid))
{
- /* Switch to correct buffer if we don't have it already */
- Buffer prev_buf = hscan->xs_cbuf;
+ Assert(!*call_again);
- hscan->xs_cbuf = ReleaseAndReadBuffer(hscan->xs_cbuf,
- hscan->xs_base.rel,
- ItemPointerGetBlockNumber(tid));
+ /* Remember this buffer's block number for next time */
+ hscan->xs_blk = ItemPointerGetBlockNumber(tid);
+
+ if (BufferIsValid(hscan->xs_cbuf))
+ ReleaseBuffer(hscan->xs_cbuf);
+
+ hscan->xs_cbuf = ReadBuffer(hscan->xs_base.rel, hscan->xs_blk);
/*
- * Prune page, but only if we weren't already on this page
+ * Prune page when it is pinned for the first time
*/
- if (prev_buf != hscan->xs_cbuf)
- heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf,
- &hscan->xs_vmbuffer);
+ heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf,
+ &hscan->xs_vmbuffer);
}
+ Assert(BufferGetBlockNumber(hscan->xs_cbuf) == hscan->xs_blk);
+ Assert(hscan->xs_blk == ItemPointerGetBlockNumber(tid));
+
/* Obtain share-lock on the buffer so we can examine visibility */
LockBuffer(hscan->xs_cbuf, BUFFER_LOCK_SHARE);
got_heap_tuple = heap_hot_search_buffer(tid,
--
2.53.0