summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMelanie Plageman <melanieplageman@gmail.com>2025-02-14 12:57:03 -0500
committerMelanie Plageman <melanieplageman@gmail.com>2025-02-14 12:57:49 -0500
commitc3e775e608f2a6d0bcfba147bf08a506827cc567 (patch)
treedb91ab96dc2230c2423b00301623274d9bef916a /src
parent9256822608f3b0636cfd88c3436cdceda7003cf3 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/vacuumlazy.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 08d89ab2bcd..74175e00534 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -2641,6 +2641,32 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
}
/*
+ * 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
*
* This routine marks LP_DEAD items in vacrel->dead_items as LP_UNUSED. Pages
@@ -2660,11 +2686,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);
@@ -2680,20 +2706,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));
@@ -2705,8 +2748,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);
@@ -2719,6 +2760,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
RecordPageWithFreeSpace(vacrel->rel, blkno, freespace);
vacuumed_pages++;
}
+
+ read_stream_end(stream);
TidStoreEndIterate(iter);
vacrel->blkno = InvalidBlockNumber;