From c19b7b82d7b0e690f3f4f55af4cbd0d6327cece1 Mon Sep 17 00:00:00 2001
From: Ubuntu <ubuntu@ip-172-31-38-230.ec2.internal>
Date: Thu, 22 May 2025 20:35:06 +0000
Subject: [PATCH v1 1/1] Correct reltuples count after a VACUUM/CLUSTER
 operation

During a VACUUM FULL or CLUSTER operation, a recently dead row
is counted as a live tuple, which causes the value of pg_class.reltuples
to be higher than it should be. This differs from an index build or a
regular vacuum, which does not count recently dead tuples as live.

Discussion: https://www.postgresql.org/message-id/flat/CACAa4VKmyz51BFAFZyKGBt9-yt8Vyk09s_26%2B%2BFHy2ngfb9k0Q%40mail.gmail.com
---
 src/backend/access/heap/heapam_handler.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index ac082fefa77..a072bcdfaa1 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -936,6 +936,13 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 		}
 	}
 
+	/*
+	 * We want to advertise a recently dead tuple as having been scanned,
+	 * but it should not be counted as a live tuple in pg_class.reltuples,
+	 * so we adjust the value here.
+	 */
+	*num_tuples = *num_tuples - *tups_recently_dead;
+
 	if (indexScan != NULL)
 		index_endscan(indexScan);
 	if (tableScan != NULL)
-- 
2.43.0

