Hi, B-tree, GiST and SP-GiST take advantage of the read stream API during vacuuming. BRIN vacuum seems like a perfect candidate for it as well. During a vacuum it reads the entire relation sequentially, page by page.
PFA the patch that migrates BRIN vacuum to the read stream API. Best regards, Arseniy Mukhin
From fcc3ed0983151791f6d6934b7137cdcf2d839857 Mon Sep 17 00:00:00 2001 From: Arseniy Mukhin <[email protected]> Date: Sun, 31 Aug 2025 15:44:17 +0300 Subject: [PATCH v1] Use streaming read I/O in BRIN vacuuming BRIN vacuum processes all index pages in physical order. Now it uses the read stream API instead of explicitly invoking ReadBuffer(). --- src/backend/access/brin/brin.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 7ff7467e462..80e85066872 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -2171,28 +2171,43 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b) static void brin_vacuum_scan(Relation idxrel, BufferAccessStrategy strategy) { - BlockNumber nblocks; - BlockNumber blkno; + BlockRangeReadStreamPrivate p; + ReadStream *stream; + Buffer buf; + + p.current_blocknum = 0; + p.last_exclusive = RelationGetNumberOfBlocks(idxrel); + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_FULL | + READ_STREAM_SEQUENTIAL | + READ_STREAM_USE_BATCHING, + strategy, + idxrel, + MAIN_FORKNUM, + block_range_read_stream_cb, + &p, + 0); /* * Scan the index in physical order, and clean up any possible mess in * each page. */ - nblocks = RelationGetNumberOfBlocks(idxrel); - for (blkno = 0; blkno < nblocks; blkno++) + while ((buf = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) { - Buffer buf; - CHECK_FOR_INTERRUPTS(); - buf = ReadBufferExtended(idxrel, MAIN_FORKNUM, blkno, - RBM_NORMAL, strategy); - brin_page_cleanup(idxrel, buf); ReleaseBuffer(buf); } + read_stream_end(stream); + /* * Update all upper pages in the index's FSM, as well. This ensures not * only that we propagate leaf-page FSM updates made by brin_page_cleanup, -- 2.43.0
