From 6be22ef20afdaaa718caee31a56a85f18fbed750 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@vondra.me>
Date: Fri, 24 Jul 2026 15:03:07 +0200
Subject: [PATCH v2 2/2] Force autoanalyze for bogus reltuples values

When checking if a relation needs ANALYZE, we calculate thresholds based
on pg_class.reltuples. If the value is bogus for some reason (e.g. due
to importing invalid stats or a bug somewhere), we may never trigger the
autovacuum/autoanalyze again.

Fixed by checking for incorrect reltuples values, and forcing ANALYZE.

Reported-by: Jan Nidzwetzki <jan@planetscale.com>
Discussion: https://postgr.es/m/518BA772-8026-412A-AA8F-A7FE4C6B3717@planetscale.com
---
 src/backend/postmaster/autovacuum.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 45abf48768a..3d6b4991679 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3314,10 +3314,22 @@ relation_needs_vacanalyze(Oid relid,
 	if (relid != StatisticRelationId &&
 		classForm->relkind != RELKIND_TOASTVALUE)
 	{
+		double		tupdensity = reltuples / Max(1.0, relpages);
+
 		scores->anl = (double) anltuples / Max(anlthresh, 1);
 		scores->anl *= autovacuum_analyze_score_weight;
 		scores->max = Max(scores->max, scores->anl);
-		if (av_enabled && anltuples > anlthresh)
+
+		/*
+		 * Analyze when enough tuples have changed.
+		 *
+		 * Force analyze when reltuples is not finite, or just impossibly
+		 * high. The invalid value (e.g. from a bad statistics import)
+		 * propagates into anlthresh, so "anltuples > anlthresh" may never
+		 * hold and the bogus value would persist.
+		 */
+		if (av_enabled &&
+			(anltuples > anlthresh || !isfinite(reltuples) || tupdensity > MaxHeapTuplesPerPage))
 			*doanalyze = true;
 	}
 
-- 
2.55.0

