Skip to content

Commit c3e775e

Browse files
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
1 parent 9256822 commit c3e775e

File tree

1 file changed

+49
-6
lines changed

1 file changed

+49
-6
lines changed

src/backend/access/heap/vacuumlazy.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,6 +2640,32 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
26402640
return allindexes;
26412641
}
26422642

2643+
/*
2644+
* Read stream callback for vacuum's third phase (second pass over the heap).
2645+
* Gets the next block from the TID store and returns it or InvalidBlockNumber
2646+
* if there are no further blocks to vacuum.
2647+
*/
2648+
static BlockNumber
2649+
vacuum_reap_lp_read_stream_next(ReadStream *stream,
2650+
void *callback_private_data,
2651+
void *per_buffer_data)
2652+
{
2653+
TidStoreIter *iter = callback_private_data;
2654+
TidStoreIterResult *iter_result;
2655+
2656+
iter_result = TidStoreIterateNext(iter);
2657+
if (iter_result == NULL)
2658+
return InvalidBlockNumber;
2659+
2660+
/*
2661+
* Save the TidStoreIterResult for later, so we can extract the offsets.
2662+
* It is safe to copy the result, according to TidStoreIterateNext().
2663+
*/
2664+
memcpy(per_buffer_data, iter_result, sizeof(*iter_result));
2665+
2666+
return iter_result->blkno;
2667+
}
2668+
26432669
/*
26442670
* lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy
26452671
*
@@ -2660,11 +2686,11 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
26602686
static void
26612687
lazy_vacuum_heap_rel(LVRelState *vacrel)
26622688
{
2689+
ReadStream *stream;
26632690
BlockNumber vacuumed_pages = 0;
26642691
Buffer vmbuffer = InvalidBuffer;
26652692
LVSavedErrInfo saved_err_info;
26662693
TidStoreIter *iter;
2667-
TidStoreIterResult *iter_result;
26682694

26692695
Assert(vacrel->do_index_vacuuming);
26702696
Assert(vacrel->do_index_cleanup);
@@ -2680,20 +2706,37 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
26802706
InvalidBlockNumber, InvalidOffsetNumber);
26812707

26822708
iter = TidStoreBeginIterate(vacrel->dead_items);
2683-
while ((iter_result = TidStoreIterateNext(iter)) != NULL)
2709+
2710+
/* Set up the read stream for vacuum's second pass through the heap */
2711+
stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE,
2712+
vacrel->bstrategy,
2713+
vacrel->rel,
2714+
MAIN_FORKNUM,
2715+
vacuum_reap_lp_read_stream_next,
2716+
iter,
2717+
sizeof(TidStoreIterResult));
2718+
2719+
while (true)
26842720
{
26852721
BlockNumber blkno;
26862722
Buffer buf;
26872723
Page page;
2724+
TidStoreIterResult *iter_result;
26882725
Size freespace;
26892726
OffsetNumber offsets[MaxOffsetNumber];
26902727
int num_offsets;
26912728

26922729
vacuum_delay_point(false);
26932730

2694-
blkno = iter_result->blkno;
2695-
vacrel->blkno = blkno;
2731+
buf = read_stream_next_buffer(stream, (void **) &iter_result);
26962732

2733+
/* The relation is exhausted */
2734+
if (!BufferIsValid(buf))
2735+
break;
2736+
2737+
vacrel->blkno = blkno = BufferGetBlockNumber(buf);
2738+
2739+
Assert(iter_result);
26972740
num_offsets = TidStoreGetBlockOffsets(iter_result, offsets, lengthof(offsets));
26982741
Assert(num_offsets <= lengthof(offsets));
26992742

@@ -2705,8 +2748,6 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
27052748
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
27062749

27072750
/* We need a non-cleanup exclusive lock to mark dead_items unused */
2708-
buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
2709-
vacrel->bstrategy);
27102751
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
27112752
lazy_vacuum_heap_page(vacrel, blkno, buf, offsets,
27122753
num_offsets, vmbuffer);
@@ -2719,6 +2760,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
27192760
RecordPageWithFreeSpace(vacrel->rel, blkno, freespace);
27202761
vacuumed_pages++;
27212762
}
2763+
2764+
read_stream_end(stream);
27222765
TidStoreEndIterate(iter);
27232766

27242767
vacrel->blkno = InvalidBlockNumber;

0 commit comments

Comments
 (0)