From b091b9051f64d28a376768dbbf17479dc1238f89 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Sun, 23 Jan 2022 21:10:38 -0800 Subject: [PATCH v7 6/6] Add all-visible FSM heuristic. When recording free space in all-frozen page, record that the page has zero free space when it has less than half BLCKSZ worth of space, according to the traditional definition. Otherwise record free space as usual. Making all-visible pages resistant to change like this can be thought of as a form of hysteresis. The page is given an opportunity to "settle" and permanently stay in the same state when the tuples on the page will never be updated or deleted. But when they are updated or deleted, the page can once again be used to store any tuple. Over time, most pages tend to settle permanently in many workloads, perhaps only on the second or third attempt. --- src/backend/access/heap/vacuumlazy.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 52cfb00ea..5608a6e19 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1238,6 +1238,13 @@ lazy_scan_heap(LVRelState *vacrel, int nworkers) */ freespace = PageGetHeapFreeSpace(page); + /* + * An all-visible page should not have its free space + * available from FSM unless it's more than half empty + */ + if (PageIsAllVisible(page) && freespace < BLCKSZ / 2) + freespace = 0; + UnlockReleaseBuffer(buf); RecordPageWithFreeSpace(vacrel->rel, blkno, freespace); continue; @@ -1375,6 +1382,13 @@ lazy_scan_heap(LVRelState *vacrel, int nworkers) { Size freespace = PageGetHeapFreeSpace(page); + /* + * An all-visible page should not have its free space available + * from FSM unless it's more than half empty + */ + if (PageIsAllVisible(page) && freespace < BLCKSZ / 2) + freespace = 0; + UnlockReleaseBuffer(buf); RecordPageWithFreeSpace(vacrel->rel, blkno, freespace); } @@ -2549,6 +2563,13 @@ lazy_vacuum_heap_rel(LVRelState *vacrel) page = BufferGetPage(buf); freespace = PageGetHeapFreeSpace(page); + /* + * An all-visible page should not have its free space available from + * FSM unless it's more than half empty + */ + if (PageIsAllVisible(page) && freespace < BLCKSZ / 2) + freespace = 0; + UnlockReleaseBuffer(buf); RecordPageWithFreeSpace(vacrel->rel, tblk, freespace); vacuumed_pages++; -- 2.30.2