public inbox for [email protected]  
help / color / mirror / Atom feed
From: Nathan Bossart <[email protected]>
Subject: [PATCH v8 2/5] always compute autovacuum scores
Date: Thu, 2 Apr 2026 13:45:48 -0500

---
 src/backend/postmaster/autovacuum.c | 114 ++++++++++++++--------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 590e4c8e44c..817025ce616 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3122,6 +3122,10 @@ relation_needs_vacanalyze(Oid relid,
 	TransactionId relfrozenxid;
 	MultiXactId relminmxid;
 	MultiXactId multiForceLimit;
+	uint32		xid_age;
+	uint32		mxid_age;
+	int			effective_xid_failsafe_age;
+	int			effective_mxid_failsafe_age;
 
 	float4		pcnt_unfrozen = 1;
 	float4		reltuples = classForm->reltuples;
@@ -3181,6 +3185,7 @@ relation_needs_vacanalyze(Oid relid,
 		: effective_multixact_freeze_max_age;
 
 	av_enabled = (relopts ? relopts->enabled : true);
+	av_enabled &= AutoVacuumingActive();
 
 	relfrozenxid = classForm->relfrozenxid;
 	relminmxid = classForm->relminmxid;
@@ -3201,65 +3206,51 @@ relation_needs_vacanalyze(Oid relid,
 	}
 	*wraparound = force_vacuum;
 
-	/* Update the score. */
-	if (force_vacuum)
-	{
-		uint32		xid_age;
-		uint32		mxid_age;
-		int			effective_xid_failsafe_age;
-		int			effective_mxid_failsafe_age;
-
-		/*
-		 * To calculate the (M)XID age portion of the score, divide the age by
-		 * its respective *_freeze_max_age parameter.
-		 */
-		xid_age = TransactionIdIsNormal(relfrozenxid) ? recentXid - relfrozenxid : 0;
-		mxid_age = MultiXactIdIsValid(relminmxid) ? recentMulti - relminmxid : 0;
-
-		scores->xid = (double) xid_age / freeze_max_age;
-		scores->mxid = (double) mxid_age / multixact_freeze_max_age;
+	/*
+	 * To calculate the (M)XID age portion of the score, divide the age by its
+	 * respective *_freeze_max_age parameter.
+	 */
+	xid_age = TransactionIdIsNormal(relfrozenxid) ? recentXid - relfrozenxid : 0;
+	mxid_age = MultiXactIdIsValid(relminmxid) ? recentMulti - relminmxid : 0;
 
-		/*
-		 * To ensure tables are given increased priority once they begin
-		 * approaching wraparound, we scale the score aggressively if the ages
-		 * surpass vacuum_failsafe_age or vacuum_multixact_failsafe_age.
-		 *
-		 * As in vacuum_xid_failsafe_check(), the effective failsafe age is no
-		 * less than 105% the value of the respective *_freeze_max_age
-		 * parameter.  Note that per-table settings could result in a low
-		 * score even if the table surpasses the failsafe settings.  However,
-		 * this is a strange enough corner case that we don't bother trying to
-		 * handle it.
-		 *
-		 * We further adjust the effective failsafe ages with the weight
-		 * parameters so that increasing them lowers the ages at which we
-		 * begin scaling aggressively.
-		 */
-		effective_xid_failsafe_age = Max(vacuum_failsafe_age,
-										 autovacuum_freeze_max_age * 1.05);
-		effective_mxid_failsafe_age = Max(vacuum_multixact_failsafe_age,
-										  autovacuum_multixact_freeze_max_age * 1.05);
+	scores->xid = (double) xid_age / freeze_max_age;
+	scores->mxid = (double) mxid_age / multixact_freeze_max_age;
 
-		if (autovacuum_freeze_score_weight > 1.0)
-			effective_xid_failsafe_age /= autovacuum_freeze_score_weight;
-		if (autovacuum_multixact_freeze_score_weight > 1.0)
-			effective_mxid_failsafe_age /= autovacuum_multixact_freeze_score_weight;
+	/*
+	 * To ensure tables are given increased priority once they begin
+	 * approaching wraparound, we scale the score aggressively if the ages
+	 * surpass vacuum_failsafe_age or vacuum_multixact_failsafe_age.
+	 *
+	 * As in vacuum_xid_failsafe_check(), the effective failsafe age is no
+	 * less than 105% the value of the respective *_freeze_max_age parameter.
+	 * Note that per-table settings could result in a low score even if the
+	 * table surpasses the failsafe settings.  However, this is a strange
+	 * enough corner case that we don't bother trying to handle it.
+	 *
+	 * We further adjust the effective failsafe ages with the weight
+	 * parameters so that increasing them lowers the ages at which we begin
+	 * scaling aggressively.
+	 */
+	effective_xid_failsafe_age = Max(vacuum_failsafe_age,
+									 autovacuum_freeze_max_age * 1.05);
+	effective_mxid_failsafe_age = Max(vacuum_multixact_failsafe_age,
+									  autovacuum_multixact_freeze_max_age * 1.05);
 
-		if (xid_age >= effective_xid_failsafe_age)
-			scores->xid = pow(scores->xid, Max(1.0, (double) xid_age / 100000000));
-		if (mxid_age >= effective_mxid_failsafe_age)
-			scores->mxid = pow(scores->mxid, Max(1.0, (double) mxid_age / 100000000));
+	if (autovacuum_freeze_score_weight > 1.0)
+		effective_xid_failsafe_age /= autovacuum_freeze_score_weight;
+	if (autovacuum_multixact_freeze_score_weight > 1.0)
+		effective_mxid_failsafe_age /= autovacuum_multixact_freeze_score_weight;
 
-		scores->xid *= autovacuum_freeze_score_weight;
-		scores->mxid *= autovacuum_multixact_freeze_score_weight;
+	if (xid_age >= effective_xid_failsafe_age)
+		scores->xid = pow(scores->xid, Max(1.0, (double) xid_age / 100000000));
+	if (mxid_age >= effective_mxid_failsafe_age)
+		scores->mxid = pow(scores->mxid, Max(1.0, (double) mxid_age / 100000000));
 
-		scores->max = Max(scores->xid, scores->mxid);
-		*dovacuum = true;
-	}
+	scores->xid *= autovacuum_freeze_score_weight;
+	scores->mxid *= autovacuum_multixact_freeze_score_weight;
 
-	/* User disabled it in pg_class.reloptions?  (But ignore if at risk) */
-	if (!av_enabled && !force_vacuum)
-		return;
+	scores->max = Max(scores->xid, scores->mxid);
+	*dovacuum |= force_vacuum;
 
 	/*
 	 * If we found stats for the table, and autovacuum is currently enabled,
@@ -3268,7 +3259,7 @@ relation_needs_vacanalyze(Oid relid,
 	 * vacuuming only, so don't vacuum (or analyze) anything that's not being
 	 * forced.
 	 */
-	if (!tabentry || !AutoVacuumingActive())
+	if (!tabentry)
 		return;
 
 	vactuples = tabentry->dead_tuples;
@@ -3312,7 +3303,7 @@ relation_needs_vacanalyze(Oid relid,
 		scores->vac = (double) vactuples / Max(vacthresh, 1);
 		scores->vac *= autovacuum_vacuum_score_weight;
 		scores->max = Max(scores->max, scores->vac);
-		*dovacuum = true;
+		*dovacuum |= av_enabled;
 	}
 
 	if (vac_ins_base_thresh >= 0 && instuples > vacinsthresh)
@@ -3320,7 +3311,7 @@ relation_needs_vacanalyze(Oid relid,
 		scores->vac_ins = (double) instuples / Max(vacinsthresh, 1);
 		scores->vac_ins *= autovacuum_vacuum_insert_score_weight;
 		scores->max = Max(scores->max, scores->vac_ins);
-		*dovacuum = true;
+		*dovacuum |= av_enabled;
 	}
 
 	/*
@@ -3334,7 +3325,16 @@ relation_needs_vacanalyze(Oid relid,
 		scores->anl = (double) anltuples / Max(anlthresh, 1);
 		scores->anl *= autovacuum_analyze_score_weight;
 		scores->max = Max(scores->max, scores->anl);
-		*doanalyze = true;
+		*doanalyze |= av_enabled;
+
+		/*
+		 * For historical reasons, we analyze even when autovacuum is disabled
+		 * for the table if at risk of wraparound.  It's not clear if this is
+		 * necessary or intentional, but it has been this way for nearly 20
+		 * years, so it seems best to avoid changing it without further
+		 * discussion.
+		 */
+		*doanalyze |= (force_vacuum && AutoVacuumingActive());
 	}
 
 	if (vac_ins_base_thresh >= 0)
-- 
2.50.1 (Apple Git-155)


--/vKBiHkEvphli8Mi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v8-0003-add-elevel-parameter-to-relation_needs_vacanalyze.patch



reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected]
  Subject: Re: [PATCH v8 2/5] always compute autovacuum scores
  In-Reply-To: <no-message-id-601573@localhost>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox