public inbox for [email protected]
help / color / mirror / Atom feedFrom: 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