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,