From: Nathan Bossart Date: Mon, 6 Apr 2026 21:56:33 +0000 (-0500) Subject: Add pg_stat_autovacuum_scores system view. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87f61f0c82;p=thirdparty%2Fpostgresql.git Add pg_stat_autovacuum_scores system view. This view contains one row for each table in the current database, showing the current autovacuum scores for that specific table. It also shows whether autovacuum would vacuum or analyze the table. Bumps catversion. Author: Sami Imseih Reviewed-by: Satyanarayana Narlapuram Reviewed-by: Bharath Rupireddy Reviewed-by: Robert Treat Discussion: https://postgr.es/m/CAA5RZ0s4xjMrB-VAnLccC7kY8d0-4806-Lsac-czJsdA1LXtAw%40mail.gmail.com --- diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 64bbc831343..652b291de15 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1168,6 +1168,12 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu 2.0 effectively doubles the analyze component score. + + + The + pg_stat_autovacuum_scores + view shows the current scores of all tables in the current database. + diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 9678877bf3d..08d5b824552 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -596,6 +596,16 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser user tables are shown. + + pg_stat_autovacuum_scorespg_stat_autovacuum_scores + + One row for each table in the current database, showing the current + autovacuum scores for that specific table. See + + pg_stat_autovacuum_scores for details. + + + pg_stat_all_indexespg_stat_all_indexes @@ -4502,6 +4512,175 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + <structname>pg_stat_autovacuum_scores</structname> + + + pg_stat_autovacuum_scores + + + + The pg_stat_autovacuum_scores view will contain one + row for each table in the current database (including TOAST tables), showing + the current autovacuum scores for that specific table. Autovacuum + prioritizes tables deemed eligible for processing based on their + score, with higher scores indicating higher + priority. See for more information. + + + + While this view generates its results the same way that autovacuum workers + do, it does so using the current source information, which might differ from + the source information that an autovacuum worker sees when it gathers its + list of tables to process. Therefore, this view is not a completely + reliable indicator of which tables autovacuum will process and what order it + will process them. + + + + <structname>pg_stat_autovacuum_scores</structname> View + + + + + Column Type + + + Description + + + + + + + + relid oid + + + Oid of the table. + + + + + + schemaname name + + + Name of the schema that the table is in. + + + + + + relname name + + + Name of the table. + + + + + + score double precision + + + Maximum value of all component scores. This is the value that + autovacuum would use to sort the list of tables to process. + + + + + + xid_score double precision + + + Transaction ID age component score. Scores greater than or equal to + indicate that + autovacuum would vacuum the table for transaction ID wraparound + prevention. + + + + + + mxid_score double precision + + + Multixact ID age component score. Scores greater than or equal to + indicate + that autovacuum would vacuum the table for multixact ID wraparound + prevention. + + + + + + vacuum_score double precision + + + Vacuum component score. Scores greater than or equal to + indicate that + autovacuum would vacuum the table (unless autovacuum is disabled). + + + + + + vacuum_insert_score double precision + + + Vacuum insert component score. Scores greater than or equal to + indicate + that autovacuum would vacuum the table (unless autovacuum is disabled). + + + + + + analyze_score double precision + + + Analyze component score. Scores greater than or equal to + indicate that + autovacuum would analyze the table (unless autovacuum is disabled). + + + + + + do_vacuum bool + + + Whether autovacuum would vacuum the table. Note that even if the + component scores indicate that autovacuum would vacuum the table, this + may be false if autovacuum is disabled. + + + + + + do_analyze bool + + + Whether autovacuum would analyze the table. Note that even if the + component scores indicate that autovacuum would analyze the table, this + may be false if autovacuum is disabled. + + + + + + for_wraparound bool + + + Whether autovacuum would vacuum the table for wraparound prevention. + + + + +
+
+ <structname>pg_stat_all_indexes</structname> diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 64ef4897571..73a1c1c4670 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -795,6 +795,24 @@ CREATE VIEW pg_stat_xact_user_tables AS WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND schemaname !~ '^pg_toast'; +CREATE VIEW pg_stat_autovacuum_scores AS + SELECT + s.oid AS relid, + n.nspname AS schemaname, + c.relname AS relname, + s.score, + s.xid_score, + s.mxid_score, + s.vacuum_score, + s.vacuum_insert_score, + s.analyze_score, + s.do_vacuum, + s.do_analyze, + s.for_wraparound + FROM pg_stat_get_autovacuum_scores() s + JOIN pg_class c on c.oid = s.oid + LEFT JOIN pg_namespace n ON n.oid = c.relnamespace; + CREATE VIEW pg_statio_all_tables AS SELECT C.oid AS relid, diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 9a38f4075d5..bd626a16363 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -80,6 +80,7 @@ #include "catalog/pg_namespace.h" #include "commands/vacuum.h" #include "common/int.h" +#include "funcapi.h" #include "lib/ilist.h" #include "libpq/pqsignal.h" #include "miscadmin.h" @@ -112,6 +113,7 @@ #include "utils/syscache.h" #include "utils/timeout.h" #include "utils/timestamp.h" +#include "utils/tuplestore.h" #include "utils/wait_event.h" @@ -3627,3 +3629,74 @@ check_av_worker_gucs(void) errdetail("The server will only start up to \"autovacuum_worker_slots\" (%d) autovacuum workers at a given time.", autovacuum_worker_slots))); } + +/* + * pg_stat_get_autovacuum_scores + * + * Returns current autovacuum scores for all relevant tables in the current + * database. + */ +Datum +pg_stat_get_autovacuum_scores(PG_FUNCTION_ARGS) +{ + int effective_multixact_freeze_max_age; + Relation rel; + TableScanDesc scan; + HeapTuple tup; + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + + InitMaterializedSRF(fcinfo, 0); + + /* some prerequisite initialization */ + effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold(); + recentXid = ReadNextTransactionId(); + recentMulti = ReadNextMultiXactId(); + + /* scan pg_class */ + rel = table_open(RelationRelationId, AccessShareLock); + scan = table_beginscan_catalog(rel, 0, NULL); + while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + Form_pg_class form = (Form_pg_class) GETSTRUCT(tup); + AutoVacOpts *avopts; + bool dovacuum; + bool doanalyze; + bool wraparound; + AutoVacuumScores scores; + Datum vals[10]; + bool nulls[10] = {false}; + + /* skip ineligible entries */ + if (form->relkind != RELKIND_RELATION && + form->relkind != RELKIND_MATVIEW && + form->relkind != RELKIND_TOASTVALUE) + continue; + if (form->relpersistence == RELPERSISTENCE_TEMP) + continue; + + avopts = extract_autovac_opts(tup, RelationGetDescr(rel)); + relation_needs_vacanalyze(form->oid, avopts, form, + effective_multixact_freeze_max_age, 0, + &dovacuum, &doanalyze, &wraparound, + &scores); + if (avopts) + pfree(avopts); + + vals[0] = ObjectIdGetDatum(form->oid); + vals[1] = Float8GetDatum(scores.max); + vals[2] = Float8GetDatum(scores.xid); + vals[3] = Float8GetDatum(scores.mxid); + vals[4] = Float8GetDatum(scores.vac); + vals[5] = Float8GetDatum(scores.vac_ins); + vals[6] = Float8GetDatum(scores.anl); + vals[7] = BoolGetDatum(dovacuum); + vals[8] = BoolGetDatum(doanalyze); + vals[9] = BoolGetDatum(wraparound); + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls); + } + table_endscan(scan); + table_close(rel, AccessShareLock); + + return (Datum) 0; +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 0cee5315b59..1602962dbe1 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202604051 +#define CATALOG_VERSION_NO 202604061 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 3ea17fc5629..99fa9a6ede2 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5673,6 +5673,13 @@ proname => 'pg_stat_get_total_autoanalyze_time', provolatile => 's', proparallel => 'r', prorettype => 'float8', proargtypes => 'oid', prosrc => 'pg_stat_get_total_autoanalyze_time' }, +{ oid => '8409', descr => 'autovacuum scores', + proname => 'pg_stat_get_autovacuum_scores', prorows => '100', proretset => 't', + provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => '', + proallargtypes => '{oid,float8,float8,float8,float8,float8,float8,bool,bool,bool}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o}', + proargnames => '{oid,score,xid_score,mxid_score,vacuum_score,vacuum_insert_score,analyze_score,do_vacuum,do_analyze,for_wraparound}', + prosrc => 'pg_stat_get_autovacuum_scores' }, { oid => '1936', descr => 'statistics: currently active backend IDs', proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't', provolatile => 's', proparallel => 'r', prorettype => 'int4', diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 45994ff0222..a65a5bf0c4f 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1860,6 +1860,21 @@ pg_stat_archiver| SELECT archived_count, last_failed_time, stats_reset FROM pg_stat_get_archiver() s(archived_count, last_archived_wal, last_archived_time, failed_count, last_failed_wal, last_failed_time, stats_reset); +pg_stat_autovacuum_scores| SELECT s.oid AS relid, + n.nspname AS schemaname, + c.relname, + s.score, + s.xid_score, + s.mxid_score, + s.vacuum_score, + s.vacuum_insert_score, + s.analyze_score, + s.do_vacuum, + s.do_analyze, + s.for_wraparound + FROM ((pg_stat_get_autovacuum_scores() s(oid, score, xid_score, mxid_score, vacuum_score, vacuum_insert_score, analyze_score, do_vacuum, do_analyze, for_wraparound) + JOIN pg_class c ON ((c.oid = s.oid))) + LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))); pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean, pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean, pg_stat_get_buf_alloc() AS buffers_alloc,