Hi, I noticed that in lazy_scan_heap(), when there are no indexes on the table being vacuumed, we don't release the lock on the heap page buffer before vacuuming the freespace map. Other call sites of FreeSpaceMapVacuumRange() hold no such lock. It seems like a waste to hold a lock we don't need.
ISTM the fix (attached) is just to move down the call to FreeSpaceMapVacuumRange() to after we've released the lock and recorded the space we just freed. - Melanie
From 27e459b357085993a35126fe55ec73eb73ae2e87 Mon Sep 17 00:00:00 2001 From: Melanie Plageman <melanieplage...@gmail.com> Date: Mon, 13 Nov 2023 16:39:25 -0500 Subject: [PATCH v1] Release lock on heap buffer before vacuuming FSM When there are no indexes on a table, we vacuum each heap block after pruning it and then update the freespace map. Periodically, we also vacuum the freespace map. This was done while unnecessarily holding a lock on the heap page. Move down the call to FreeSpaceMapVacuumRange() so that we have already recorded any newly freed space and released the lock on the heap page. --- src/backend/access/heap/vacuumlazy.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 6985d299b2..8b729828ce 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1046,18 +1046,6 @@ lazy_scan_heap(LVRelState *vacrel) /* Forget the LP_DEAD items that we just vacuumed */ dead_items->num_items = 0; - /* - * Periodically perform FSM vacuuming to make newly-freed - * space visible on upper FSM pages. Note we have not yet - * performed FSM processing for blkno. - */ - if (blkno - next_fsm_block_to_vacuum >= VACUUM_FSM_EVERY_PAGES) - { - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, - blkno); - next_fsm_block_to_vacuum = blkno; - } - /* * Now perform FSM processing for blkno, and move on to next * page. @@ -1071,6 +1059,18 @@ lazy_scan_heap(LVRelState *vacrel) UnlockReleaseBuffer(buf); RecordPageWithFreeSpace(vacrel->rel, blkno, freespace); + + /* + * Periodically perform FSM vacuuming to make newly-freed + * space visible on upper FSM pages. + */ + if (blkno - next_fsm_block_to_vacuum >= VACUUM_FSM_EVERY_PAGES) + { + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, + blkno); + next_fsm_block_to_vacuum = blkno; + } + continue; } -- 2.37.2