v18-0003-Use-streaming-read-I-O-in-VACUUM-s-third-phase.patch
text/x-patch
Filename: v18-0003-Use-streaming-read-I-O-in-VACUUM-s-third-phase.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v18-0003
Subject: Use streaming read I/O in VACUUM's third phase
| File | + | − |
|---|---|---|
| src/backend/access/heap/vacuumlazy.c | 49 | 6 |
From 7cd9bd45b2e6a7da333b3f6c1ec46bc9fa90ba8b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Thu, 13 Feb 2025 17:34:18 -0500
Subject: [PATCH v18 3/3] Use streaming read I/O in VACUUM's third phase
Make vacuum's third phase (its second pass over the heap), which reaps
dead items collected in the first phase and marks them as reusable, use
the read stream API. This commit adds a new read stream callback,
vacuum_reap_lp_read_stream_next(), that looks ahead in the TidStore and
returns the next block number to read for vacuum.
Author: Melanie Plageman <melanieplageman@gmail.com>
Co-authored-by: Thomas Munro <thomas.munro@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKGKN3oy0bN_3yv8hd78a4%2BM1tJC9z7mD8%2Bf%2ByA%2BGeoFUwQ%40mail.gmail.com
---
src/backend/access/heap/vacuumlazy.c | 55 +++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 6 deletions(-)
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index ea19eed57bf..3c4aa17892e 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -2638,6 +2638,32 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
return allindexes;
}
+/*
+ * Read stream callback for vacuum's third phase (second pass over the heap).
+ * Gets the next block from the TID store and returns it or InvalidBlockNumber
+ * if there are no further blocks to vacuum.
+ */
+static BlockNumber
+vacuum_reap_lp_read_stream_next(ReadStream *stream,
+ void *callback_private_data,
+ void *per_buffer_data)
+{
+ TidStoreIter *iter = callback_private_data;
+ TidStoreIterResult *iter_result;
+
+ iter_result = TidStoreIterateNext(iter);
+ if (iter_result == NULL)
+ return InvalidBlockNumber;
+
+ /*
+ * Save the TidStoreIterResult for later, so we can extract the offsets.
+ * It is safe to copy the result, according to TidStoreIterateNext().
+ */
+ memcpy(per_buffer_data, iter_result, sizeof(*iter_result));
+
+ return iter_result->blkno;
+}
+
/*
* lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy
*
@@ -2658,11 +2684,11 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
static void
lazy_vacuum_heap_rel(LVRelState *vacrel)
{
+ ReadStream *stream;
BlockNumber vacuumed_pages = 0;
Buffer vmbuffer = InvalidBuffer;
LVSavedErrInfo saved_err_info;
TidStoreIter *iter;
- TidStoreIterResult *iter_result;
Assert(vacrel->do_index_vacuuming);
Assert(vacrel->do_index_cleanup);
@@ -2678,20 +2704,37 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
InvalidBlockNumber, InvalidOffsetNumber);
iter = TidStoreBeginIterate(vacrel->dead_items);
- while ((iter_result = TidStoreIterateNext(iter)) != NULL)
+
+ /* Set up the read stream for vacuum's second pass through the heap */
+ stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE,
+ vacrel->bstrategy,
+ vacrel->rel,
+ MAIN_FORKNUM,
+ vacuum_reap_lp_read_stream_next,
+ iter,
+ sizeof(TidStoreIterResult));
+
+ while (true)
{
BlockNumber blkno;
Buffer buf;
Page page;
+ TidStoreIterResult *iter_result;
Size freespace;
OffsetNumber offsets[MaxOffsetNumber];
int num_offsets;
vacuum_delay_point(false);
- blkno = iter_result->blkno;
- vacrel->blkno = blkno;
+ buf = read_stream_next_buffer(stream, (void **) &iter_result);
+ /* The relation is exhausted */
+ if (!BufferIsValid(buf))
+ break;
+
+ vacrel->blkno = blkno = BufferGetBlockNumber(buf);
+
+ Assert(iter_result);
num_offsets = TidStoreGetBlockOffsets(iter_result, offsets, lengthof(offsets));
Assert(num_offsets <= lengthof(offsets));
@@ -2703,8 +2746,6 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
/* We need a non-cleanup exclusive lock to mark dead_items unused */
- buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
- vacrel->bstrategy);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
lazy_vacuum_heap_page(vacrel, blkno, buf, offsets,
num_offsets, vmbuffer);
@@ -2717,6 +2758,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
RecordPageWithFreeSpace(vacrel->rel, blkno, freespace);
vacuumed_pages++;
}
+
+ read_stream_end(stream);
TidStoreEndIterate(iter);
vacrel->blkno = InvalidBlockNumber;
--
2.34.1