v5-0001-Use-streaming-read-API-in-pgstatindex-functions.patch
application/octet-stream
Filename: v5-0001-Use-streaming-read-API-in-pgstatindex-functions.patch
Type: application/octet-stream
Part: 0
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 v5-0001
Subject: Use streaming read API in pgstatindex functions
| File | + | − |
|---|---|---|
| contrib/pgstattuple/pgstatindex.c | 48 | 9 |
From fe917cbd3c5dc5e62a5472434e12ad611463e40a Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Thu, 16 Oct 2025 17:04:23 +0800
Subject: [PATCH v5] Use streaming read API in pgstatindex functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Replace synchronous ReadBufferExtended() loops with the streaming read
API in pgstatindex_impl() and pgstathashindex().
Author: Xuneng Zhou <xunengzhou@gmail.com>Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: wenhui qiu <qiuwenhuifx@gmail.com>
Reviewed-by: Shinya Kato <shinya11.kato@gmail.com>
---
contrib/pgstattuple/pgstatindex.c | 57 ++++++++++++++++++++++++++-----
1 file changed, 48 insertions(+), 9 deletions(-)
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index 40823d54fca..e9c06de4e52 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 = BTREE_METAPAGE + 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);
@@ -322,11 +340,12 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
else
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 +615,8 @@ pgstathashindex(PG_FUNCTION_ARGS)
HashMetaPage metap;
float8 free_percent;
uint64 total_space;
+ BlockRangeReadStreamPrivate p;
+ ReadStream *stream;
rel = relation_open(relid, AccessShareLock);
@@ -636,7 +657,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 = HASH_METAPAGE + 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 +681,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);
@@ -690,6 +726,9 @@ pgstathashindex(PG_FUNCTION_ARGS)
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