From b757f686ae2e3773b2569b9cb934381c0d46407f Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Sun, 13 Feb 2022 11:52:22 -0800
Subject: [PATCH v1] Avoid vac_estimate_reltuples distortion.

---
 src/backend/commands/vacuum.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index b6767a5ff..4f0ff1069 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -1238,6 +1238,22 @@ vac_estimate_reltuples(Relation relation,
 	if (scanned_pages == 0)
 		return old_rel_tuples;
 
+	/*
+	 * We must not allow successive VACUUM operations that scan the same few
+	 * pages again and again to make the spurious assumption that it's a
+	 * random sample each time.  This will eventually result in very distorted
+	 * tuple densities for the pages that were only ever scanned once, after
+	 * tuples were initially inserted.
+	 *
+	 * If the relation is exactly the same size as it was at the end of the
+	 * last VACUUM, and only a few of its pages (less than a quasi-arbitrary
+	 * threshold of 2%) were scanned during the ongoing VACUUM, then assume
+	 * that reltuples has not changed at all.
+	 */
+	if (old_rel_pages == total_pages &&
+		scanned_pages < (double) total_pages * 0.02)
+		return old_rel_tuples;
+
 	/*
 	 * If old density is unknown, we can't do much except scale up
 	 * scanned_tuples to match total_pages.
-- 
2.30.2

