From 2d6560e2da9635d06d8fceba6ef8410eb89bdd01 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Sun, 17 Jul 2022 18:50:13 -0700 Subject: [PATCH v1] Show when autovacuum is insert driven in log. Teach the logging code controlled by log_autovacuum_min_duration to display more information about why its autovacuum worker was launched in the first place. Show the user distinct output when the insert-based thresholds were the triggering condition. It's sometimes far from obvious why an autovacuum worker was launched without this new instrumentation. It's useful to give feedback on the triggering condition, to guide tuning efforts by DBAs. Note that we consider insert-driven autovacuums to be a distinct category from antiwraparound autovacuums in all cases (though of course any VACUUM can end up as an aggressive VACUUM). --- src/include/commands/vacuum.h | 3 ++- src/backend/access/heap/vacuumlazy.c | 12 +++++++++- src/backend/commands/vacuum.c | 3 ++- src/backend/postmaster/autovacuum.c | 36 +++++++++++++++++++--------- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index f38e1148f..7e2d8e7b5 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -220,7 +220,8 @@ typedef struct VacuumParams * use default */ int multixact_freeze_table_age; /* multixact age at which to scan * whole table */ - bool is_wraparound; /* force a for-wraparound vacuum */ + bool is_wraparound; /* anti-wraparound autovacuum? */ + bool is_insert; /* autovacuum for inserted tuples? */ int log_min_duration; /* minimum execution threshold in ms at * which autovacuum is logged, -1 to use * default */ diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index b802ed247..653ea28e0 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -659,7 +659,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * Aggressiveness already reported earlier, in dedicated * VACUUM VERBOSE ereport */ - Assert(!params->is_wraparound); + Assert(!params->is_wraparound && !params->is_insert); msgfmt = _("finished vacuuming \"%s.%s.%s\": index scans: %d\n"); } else if (params->is_wraparound) @@ -670,13 +670,23 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * implies aggressive. Produce distinct output for the corner * case all the same, just in case. */ + Assert(!params->is_insert); if (aggressive) msgfmt = _("automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"); else msgfmt = _("automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"); } + else if (params->is_insert) + { + /* Inserted tuples crossed autovacuum.c's threshold */ + if (aggressive) + msgfmt = _("automatic aggressive vacuum for inserted tuples of table \"%s.%s.%s\": index scans: %d\n"); + else + msgfmt = _("automatic vacuum for inserted tuples of table \"%s.%s.%s\": index scans: %d\n"); + } else { + /* Dead tuples crossed autovacuum.c's threshold */ if (aggressive) msgfmt = _("automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n"); else diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 8df25f59d..a623678c0 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -265,8 +265,9 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel) params.multixact_freeze_table_age = -1; } - /* user-invoked vacuum is never "for wraparound" */ + /* user-invoked vacuum is never "for wraparound" or "for inserts" */ params.is_wraparound = false; + params.is_insert = false; /* user-invoked vacuum uses VACOPT_VERBOSE instead of log_min_duration */ params.log_min_duration = -1; diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 70a9176c5..ad90e8e67 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -329,12 +329,14 @@ static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map, static void recheck_relation_needs_vacanalyze(Oid relid, AutoVacOpts *avopts, Form_pg_class classForm, int effective_multixact_freeze_max_age, - bool *dovacuum, bool *doanalyze, bool *wraparound); + bool *dovacuum, bool *doanalyze, + bool *wraparound, bool *inserts); static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, - bool *dovacuum, bool *doanalyze, bool *wraparound); + bool *dovacuum, bool *doanalyze, + bool *wraparound, bool *inserts); static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy); @@ -2063,6 +2065,7 @@ do_autovacuum(void) bool dovacuum; bool doanalyze; bool wraparound; + bool inserts; if (classForm->relkind != RELKIND_RELATION && classForm->relkind != RELKIND_MATVIEW) @@ -2103,7 +2106,8 @@ do_autovacuum(void) /* Check if it needs vacuum or analyze */ relation_needs_vacanalyze(relid, relopts, classForm, tabentry, effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); + &dovacuum, &doanalyze, + &wraparound, &inserts); /* Relations that need work are added to table_oids */ if (dovacuum || doanalyze) @@ -2156,6 +2160,7 @@ do_autovacuum(void) bool dovacuum; bool doanalyze; bool wraparound; + bool inserts; /* * We cannot safely process other backends' temp tables, so skip 'em. @@ -2186,7 +2191,8 @@ do_autovacuum(void) relation_needs_vacanalyze(relid, relopts, classForm, tabentry, effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); + &dovacuum, &doanalyze, + &wraparound, &inserts); /* ignore analyze for toast tables */ if (dovacuum) @@ -2761,7 +2767,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, bool dovacuum; bool doanalyze; autovac_table *tab = NULL; - bool wraparound; + bool wraparound, + inserts; AutoVacOpts *avopts; /* fetch the relation's relcache entry */ @@ -2788,7 +2795,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, recheck_relation_needs_vacanalyze(relid, avopts, classForm, effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); + &dovacuum, &doanalyze, + &wraparound, &inserts); /* OK, it needs something done */ if (doanalyze || dovacuum) @@ -2869,6 +2877,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age; tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age; tab->at_params.is_wraparound = wraparound; + tab->at_params.is_insert = inserts; tab->at_params.log_min_duration = log_min_duration; tab->at_vacuum_cost_limit = vac_cost_limit; tab->at_vacuum_cost_delay = vac_cost_delay; @@ -2904,7 +2913,8 @@ recheck_relation_needs_vacanalyze(Oid relid, int effective_multixact_freeze_max_age, bool *dovacuum, bool *doanalyze, - bool *wraparound) + bool *wraparound, + bool *inserts) { PgStat_StatTabEntry *tabentry; @@ -2914,7 +2924,8 @@ recheck_relation_needs_vacanalyze(Oid relid, relation_needs_vacanalyze(relid, avopts, classForm, tabentry, effective_multixact_freeze_max_age, - dovacuum, doanalyze, wraparound); + dovacuum, doanalyze, + wraparound, inserts); /* ignore ANALYZE for toast tables */ if (classForm->relkind == RELKIND_TOASTVALUE) @@ -2967,7 +2978,8 @@ relation_needs_vacanalyze(Oid relid, /* output params below */ bool *dovacuum, bool *doanalyze, - bool *wraparound) + bool *wraparound, + bool *inserts) { bool force_vacuum; bool av_enabled; @@ -3058,6 +3070,7 @@ relation_needs_vacanalyze(Oid relid, MultiXactIdPrecedes(classForm->relminmxid, multiForceLimit); } *wraparound = force_vacuum; + *inserts = false; /* for now */ /* User disabled it in pg_class.reloptions? (But ignore if at risk) */ if (!av_enabled && !force_vacuum) @@ -3104,8 +3117,9 @@ relation_needs_vacanalyze(Oid relid, vactuples, vacthresh, anltuples, anlthresh); /* Determine if this table needs vacuum or analyze. */ - *dovacuum = force_vacuum || (vactuples > vacthresh) || - (vac_ins_base_thresh >= 0 && instuples > vacinsthresh); + *inserts = !force_vacuum && vac_ins_base_thresh >= 0 && + instuples > vacinsthresh; + *dovacuum = force_vacuum || (vactuples > vacthresh) || *inserts; *doanalyze = (anltuples > anlthresh); } else -- 2.32.0