v4-0001-pgstattuple-Use-streaming-read-API-in-pgstatindex.patch
application/octet-stream
Filename: v4-0001-pgstattuple-Use-streaming-read-API-in-pgstatindex.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v4-0001
Subject: pgstattuple: Use streaming read API in pgstatindex functions
| File | + | − |
|---|---|---|
| contrib/pgstattuple/pgstatindex.c | 49 | 8 |
From a34e0aacf5b85f161ff1d53760bd5c64ae08cd2e Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Mon, 13 Oct 2025 19:32:03 +0800
Subject: [PATCH v4] pgstattuple: Use streaming read API in pgstatindex
functions
Replace synchronous ReadBufferExtended() loops with the streaming read
API in pgstatindex_impl() and pgstathashindex().
---
contrib/pgstattuple/pgstatindex.c | 57 ++++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 8 deletions(-)
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index 40823d54fca..30c0dd1b111 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -37,6 +37,7 @@
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
+#include "storage/read_stream.h"
#include "utils/rel.h"
#include "utils/varlena.h"
@@ -217,6 +218,8 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
BlockNumber blkno;
BTIndexStat indexStat;
BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ BlockRangeReadStreamPrivate p;
+ ReadStream *stream;
if (!IS_INDEX(rel) || !IS_BTREE(rel))
ereport(ERROR,
@@ -273,10 +276,26 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
indexStat.fragments = 0;
/*
- * Scan all blocks except the metapage
+ * Scan all blocks except the metapage (0th page) using streaming reads
*/
nblocks = RelationGetNumberOfBlocks(rel);
+ p.current_blocknum = 1;
+ p.last_exclusive = nblocks;
+
+ /*
+ * It is safe to use batchmode as block_range_read_stream_cb takes no
+ * locks.
+ */
+ stream = read_stream_begin_relation(READ_STREAM_FULL |
+ READ_STREAM_USE_BATCHING,
+ bstrategy,
+ rel,
+ MAIN_FORKNUM,
+ block_range_read_stream_cb,
+ &p,
+ 0);
+
for (blkno = 1; blkno < nblocks; blkno++)
{
Buffer buffer;
@@ -285,8 +304,7 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
CHECK_FOR_INTERRUPTS();
- /* Read and lock buffer */
- buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ buffer = read_stream_next_buffer(stream, NULL);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = BufferGetPage(buffer);
@@ -323,10 +341,12 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
indexStat.internal_pages++;
/* Unlock and release buffer */
- LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- ReleaseBuffer(buffer);
+ UnlockReleaseBuffer(buffer);
}
+ Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
+ read_stream_end(stream);
+
relation_close(rel, AccessShareLock);
/*----------------------------
@@ -596,6 +616,8 @@ pgstathashindex(PG_FUNCTION_ARGS)
HashMetaPage metap;
float8 free_percent;
uint64 total_space;
+ BlockRangeReadStreamPrivate p;
+ ReadStream *stream;
rel = relation_open(relid, AccessShareLock);
@@ -636,7 +658,23 @@ pgstathashindex(PG_FUNCTION_ARGS)
/* prepare access strategy for this index */
bstrategy = GetAccessStrategy(BAS_BULKREAD);
- /* Start from blkno 1 as 0th block is metapage */
+ /* Scan all blocks except the metapage (0th page) using streaming reads */
+ p.current_blocknum = 1;
+ p.last_exclusive = nblocks;
+
+ /*
+ * It is safe to use batchmode as block_range_read_stream_cb takes no
+ * locks.
+ */
+ stream = read_stream_begin_relation(READ_STREAM_FULL |
+ READ_STREAM_USE_BATCHING,
+ bstrategy,
+ rel,
+ MAIN_FORKNUM,
+ block_range_read_stream_cb,
+ &p,
+ 0);
+
for (blkno = 1; blkno < nblocks; blkno++)
{
Buffer buf;
@@ -644,8 +682,7 @@ pgstathashindex(PG_FUNCTION_ARGS)
CHECK_FOR_INTERRUPTS();
- buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
- bstrategy);
+ buf = read_stream_next_buffer(stream, NULL);
LockBuffer(buf, BUFFER_LOCK_SHARE);
page = BufferGetPage(buf);
@@ -687,9 +724,13 @@ pgstathashindex(PG_FUNCTION_ARGS)
opaque->hasho_flag, RelationGetRelationName(rel),
BufferGetBlockNumber(buf))));
}
+ /* Unlock and release buffer */
UnlockReleaseBuffer(buf);
}
+ Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
+ read_stream_end(stream);
+
/* Done accessing the index */
index_close(rel, AccessShareLock);
--
2.51.0