From c861e77d627be8cc8cf2eda540e1f268ce47ed7b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 4 Dec 2024 16:40:16 -0500
Subject: [PATCH] Track skippable blocks scanned

Add counters and logging to vacuum to track what skippable pages were
scanned due to SKIP_PAGES_THRESHOLD and which of those were frozen.
---
 src/backend/access/heap/vacuumlazy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 6a3588cf817..8af64e1a720 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -214,6 +214,9 @@ typedef struct LVRelState
 	BlockNumber next_unskippable_block; /* next unskippable block */
 	bool		next_unskippable_allvis;	/* its visibility status */
 	Buffer		next_unskippable_vmbuffer;	/* buffer containing its VM bit */
+
+	BlockNumber skippable_blocks_scanned;
+	BlockNumber frozen_skippable_blocks_scanned;
 } LVRelState;
 
 /* Struct for saving and restoring vacuum error information. */
@@ -427,6 +430,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
 	vacrel->live_tuples = 0;
 	vacrel->recently_dead_tuples = 0;
 	vacrel->missed_dead_tuples = 0;
+	vacrel->skippable_blocks_scanned = 0;
+	vacrel->frozen_skippable_blocks_scanned = 0;
 
 	/*
 	 * Get cutoffs that determine which deleted tuples are considered DEAD,
@@ -664,6 +669,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
 							 vacrel->scanned_pages,
 							 orig_rel_pages == 0 ? 100.0 :
 							 100.0 * vacrel->scanned_pages / orig_rel_pages);
+			appendStringInfo(&buf, _("skippable blocks scanned: %u. frozen skippable blocks scanned: %u.\n"),
+					vacrel->skippable_blocks_scanned,
+					vacrel->frozen_skippable_blocks_scanned);
 			appendStringInfo(&buf,
 							 _("tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n"),
 							 (long long) vacrel->tuples_deleted,
@@ -1150,13 +1158,28 @@ heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno,
 	/* Now we must be in one of the two remaining states: */
 	if (next_block < vacrel->next_unskippable_block)
 	{
+		uint8 vmbits = 0;
+		Buffer vmbuffer = InvalidBuffer;
+
 		/*
 		 * 2. We are processing a range of blocks that we could have skipped
 		 * but chose not to.  We know that they are all-visible in the VM,
 		 * otherwise they would've been unskippable.
 		 */
+		vacrel->skippable_blocks_scanned++;
+
 		*blkno = vacrel->current_block = next_block;
 		*all_visible_according_to_vm = true;
+
+		vmbits = visibilitymap_get_status(vacrel->rel,
+				vacrel->current_block,
+				&vmbuffer);
+		if (vmbits & VISIBILITYMAP_ALL_FROZEN)
+			vacrel->frozen_skippable_blocks_scanned++;
+
+		if (vmbuffer != InvalidBuffer)
+			ReleaseBuffer(vmbuffer);
+
 		return true;
 	}
 	else
-- 
2.34.1

