Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w8qw3-000waG-1x for pgsql-hackers@arkaria.postgresql.org; Sat, 04 Apr 2026 02:40:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w8qw0-00F6EJ-2E for pgsql-hackers@arkaria.postgresql.org; Sat, 04 Apr 2026 02:40:29 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w8qw0-00F6EB-19 for pgsql-hackers@lists.postgresql.org; Sat, 04 Apr 2026 02:40:28 +0000 Received: from mail-oi1-x22a.google.com ([2607:f8b0:4864:20::22a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w8qvy-00000000U74-16rA for pgsql-hackers@postgresql.org; Sat, 04 Apr 2026 02:40:28 +0000 Received: by mail-oi1-x22a.google.com with SMTP id 5614622812f47-47018d3416aso331794b6e.3 for ; Fri, 03 Apr 2026 19:40:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775270425; x=1775875225; darn=postgresql.org; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=+BV7CYdxos5nqGarw9fj+ow9dVjNiYiiJwDmen1vKFs=; b=mEFiaMmuu5/h3YpU5Ncr/LbIpM066E3JxuUwfGoQtW77lsC9CLAM3WE+eNVKOd4GER fPIJAIdRQiElUNRtV7x7Xf+69BpkXyqcEIVe+eoRGJUCnFyT1bF130HYqnaCXNdAaT3U 8tubvBE9xyaI0Khq9CAkPo/27AMhSnrfGYTxyQIc5VjJ1HQwitodAkeu0zbRm7zTx1z6 idHZRuNDXjdA+9yCy0n9RDFlPBqJl1SDFFVlUu9KMu+zXwGMizchC/hUePUlhnpzO094 7/m4VmXrAic5tMEEI8VOAdZpOmunPPB5OUG30ihdp8rJEU98m1tEtMi5ncG7JMDY5tds wKFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775270425; x=1775875225; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+BV7CYdxos5nqGarw9fj+ow9dVjNiYiiJwDmen1vKFs=; b=FxR5hIpsuw7pntw9pigYiE1M+7jqGdZq2wuxBfJH0aLlm0hWdPeYAhIlLcQMFPjp74 gGPlxwjSa6G4frefzCnlkOGH7BZx4vx1REdCYQ0BWiWct/q7FaQOqY5fhVAciIfdHyzY 2gBal/dUU8J3szLsAazDcYSnYNogjzPdNufKP4KLk4mkAFMDGip4WQaTvJjtBE5j9CTY KnjMWPq4Q9x46AW6/4ngvVMa4BI1HQe2bi6mvNWOqb55G2DYmjMDNjvMFdQomsHDZ9LJ wGoxy91vHYPxmAcOmXmpsZNXy4VEpuoW0JekpMZJsKUKyoILILyu/V0QEHZ6wuGg3FQY 8n5g== X-Forwarded-Encrypted: i=1; AJvYcCVuloWAYjaXJgYF8LRzhCy3tDJXKJ7Bdt01sd3pL+yEhAPnyeyDx8lAakZ5TVgps5guvm2jRyk8d7IEHvi9@postgresql.org X-Gm-Message-State: AOJu0YwlD0tez+j5fVXnzvplyT2bW5OA1T0LhdybmVe+RhN4HoKfdLkG p9XzuNGgn0UWZBC8uTdFQ8nL1v8bgrIJyQ6i3xjzGO0LUVNozj+52Dua X-Gm-Gg: ATEYQzzluCrNl/K+Z/D8kVaLhNPO822B1Pugsh4jYQVOKundmAGs59t66bAN1mJhN3c d9XoPUc3IKeP6H05ryHk+idiVAeSBRx/e14IaY7JgzWM131b4EjxD3QPgnV4ikFBtPYUan5QuvM 8PcprZSDlYaohVddxtFFO4hob06nqnZ5iW+RklSWv7Tcq7UIQxp9Ik9UdLqkPJumKwcRYr1yyts gH+BMmNTsqpT6IV96Ug7vLaqdSBqs5EgDtrd9K14cYLExIQQraUrXcsMUDo772gB4o18f772eay AKFOIBiIoNWPKglWyb9pv26vFXyOrb/d8YMfdUqmXaC2Il2ImQH7Mmp0dQbb/9MXkbz/YbtX+xP Cf8SHpdqSfp1uV9d8/ispZUK37b7WiimouoGrvSWi/Xnm+OGu5fpk0ucrfEellbPhE5Oxvm3Qri y//9wi1yWXPyP2Gs9NbhlroENxcwi6fjLfWgHlvsuD4lg6SomSiLLBGNH67M0iid3NruYfVDz6B eHxEdGIQh76kv1wvCSlfQ== X-Received: by 2002:a05:6808:bc2:b0:46a:7718:c519 with SMTP id 5614622812f47-46efb3de884mr2645635b6e.38.1775270424772; Fri, 03 Apr 2026 19:40:24 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-422eb3c9e06sm5456503fac.15.2026.04.03.19.40.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 19:40:23 -0700 (PDT) Date: Fri, 3 Apr 2026 21:40:21 -0500 From: Nathan Bossart To: Sami Imseih Cc: Bharath Rupireddy , Robert Treat , satyanarlapuram@gmail.com, pgsql-hackers Subject: Re: Add pg_stat_autovacuum_priority Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="VsQ7gtq8Z1iRN55c" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --VsQ7gtq8Z1iRN55c Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit I committed 0001-0003. Here is a new version of the last two patches. Some notes: * Instead of renaming recheck_relation_needs_vacanalyze(), I followed Álvaro's suggestion to remove that function and instead fetch the stats within relation_needs_vacanalyze() itself. * Per your feedback, I renamed the view back to pg_stat_autovacuum_scores. * Instead of limiting the view to pg_read_all_stats, I've left it accessible to all users. AFAICT there's nothing sensitive here. * I reworked the column descriptions a bit to make it clear that values >= 1.0 mean autovacuum will process it (except if autovacuum is disabled). WDYT? -- nathan --VsQ7gtq8Z1iRN55c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0001-refactor-autovacuum-subroutine-in-preparation-for.patch From de3f07ff7f3c765bd5a63b97ed90f19a5c131579 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 2 Apr 2026 14:17:11 -0500 Subject: [PATCH v9 1/2] refactor autovacuum subroutine in preparation for system view --- src/backend/postmaster/autovacuum.c | 73 ++++++----------------------- 1 file changed, 15 insertions(+), 58 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 8400e6722cc..1be1ba8a25f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -370,13 +370,8 @@ static void FreeWorkerInfo(int code, Datum arg); static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, int effective_multixact_freeze_max_age); -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); static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, - PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, int elevel, bool *dovacuum, bool *doanalyze, bool *wraparound, @@ -2029,7 +2024,6 @@ do_autovacuum(void) while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); - PgStat_StatTabEntry *tabentry; AutoVacOpts *relopts; Oid relid; bool dovacuum; @@ -2070,11 +2064,9 @@ do_autovacuum(void) /* Fetch reloptions and the pgstat entry for this table */ relopts = extract_autovac_opts(tuple, pg_class_desc); - tabentry = pgstat_fetch_stat_tabentry_ext(classForm->relisshared, - relid); /* Check if it needs vacuum or analyze */ - relation_needs_vacanalyze(relid, relopts, classForm, tabentry, + relation_needs_vacanalyze(relid, relopts, classForm, effective_multixact_freeze_max_age, DEBUG3, &dovacuum, &doanalyze, &wraparound, @@ -2121,8 +2113,6 @@ do_autovacuum(void) /* Release stuff to avoid per-relation leakage */ if (relopts) pfree(relopts); - if (tabentry) - pfree(tabentry); } table_endscan(relScan); @@ -2137,7 +2127,6 @@ do_autovacuum(void) while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); - PgStat_StatTabEntry *tabentry; Oid relid; AutoVacOpts *relopts; bool free_relopts = false; @@ -2171,11 +2160,7 @@ do_autovacuum(void) relopts = &hentry->ar_reloptions; } - /* Fetch the pgstat entry for this table */ - tabentry = pgstat_fetch_stat_tabentry_ext(classForm->relisshared, - relid); - - relation_needs_vacanalyze(relid, relopts, classForm, tabentry, + relation_needs_vacanalyze(relid, relopts, classForm, effective_multixact_freeze_max_age, DEBUG3, &dovacuum, &doanalyze, &wraparound, @@ -2194,8 +2179,6 @@ do_autovacuum(void) /* Release stuff to avoid leakage */ if (free_relopts) pfree(relopts); - if (tabentry) - pfree(tabentry); } table_endscan(relScan); @@ -2834,6 +2817,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, bool wraparound; AutoVacOpts *avopts; bool free_avopts = false; + AutoVacuumScores scores; /* fetch the relation's relcache entry */ classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); @@ -2859,9 +2843,11 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, avopts = &hentry->ar_reloptions; } - recheck_relation_needs_vacanalyze(relid, avopts, classForm, - effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); + relation_needs_vacanalyze(relid, avopts, classForm, + effective_multixact_freeze_max_age, + DEBUG3, + &dovacuum, &doanalyze, &wraparound, + &scores); /* OK, it needs something done */ if (doanalyze || dovacuum) @@ -2970,41 +2956,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, return tab; } -/* - * recheck_relation_needs_vacanalyze - * - * Subroutine for table_recheck_autovac. - * - * Fetch the pgstat of a relation and recheck whether a relation - * needs to be vacuumed or analyzed. - */ -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) -{ - PgStat_StatTabEntry *tabentry; - AutoVacuumScores scores; - - /* fetch the pgstat table entry */ - tabentry = pgstat_fetch_stat_tabentry_ext(classForm->relisshared, - relid); - - relation_needs_vacanalyze(relid, avopts, classForm, tabentry, - effective_multixact_freeze_max_age, - DEBUG3, - dovacuum, doanalyze, wraparound, - &scores); - - /* Release tabentry to avoid leakage */ - if (tabentry) - pfree(tabentry); -} - /* * relation_needs_vacanalyze * @@ -3089,7 +3040,6 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, - PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, int elevel, /* output params below */ @@ -3098,6 +3048,7 @@ relation_needs_vacanalyze(Oid relid, bool *wraparound, AutoVacuumScores *scores) { + PgStat_StatTabEntry *tabentry; bool force_vacuum; bool av_enabled; @@ -3265,6 +3216,8 @@ relation_needs_vacanalyze(Oid relid, * vacuuming only, so don't vacuum (or analyze) anything that's not being * forced. */ + tabentry = pgstat_fetch_stat_tabentry_ext(classForm->relisshared, + relid); if (!tabentry) return; @@ -3353,6 +3306,10 @@ relation_needs_vacanalyze(Oid relid, vactuples, vacthresh, scores->vac, anltuples, anlthresh, scores->anl, scores->xid, scores->mxid); + + /* Release tabentry to avoid leakage */ + if (tabentry) + pfree(tabentry); } /* -- 2.50.1 (Apple Git-155) --VsQ7gtq8Z1iRN55c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0002-add-pg_stat_autovacuum_scores-system-view.patch From edfa049c389e44e5d23a239888f6b0864d2149ad Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 2 Apr 2026 15:47:19 -0500 Subject: [PATCH v9 2/2] add pg_stat_autovacuum_scores system view --- doc/src/sgml/maintenance.sgml | 6 ++ doc/src/sgml/monitoring.sgml | 137 +++++++++++++++++++++++++++ src/backend/catalog/system_views.sql | 15 +++ src/backend/postmaster/autovacuum.c | 70 ++++++++++++++ src/include/catalog/pg_proc.dat | 7 ++ src/test/regress/expected/rules.out | 12 +++ 6 files changed, 247 insertions(+) diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 0d2a28207ed..906aca2c228 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1164,6 +1164,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 312374da5e0..34e3051c400 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,133 @@ 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. See + for more information. + + + + <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 uses to sort the list of tables to process. Scores greater + than or equal to 1.0 indicate the table will be + processed (unless autovacuum is disabled and neither + xid_score nor mxid_score are + greater than or equal to 1.0). + + + + + + xid_score double precision + + + Transaction ID age component score. Scores greater than or equal to + 1.0 indicate the table will be vacuumed. + + + + + + mxid_score double precision + + + Multixact ID age component score. Scores greater than or equal to + 1.0 indicate the table will be vacuumed. + + + + + + vacuum_score double precision + + + Vacuum component score. Scores greater than or equal to + 1.0 indicate the table will be vacuumed (unless + autovacuum is disabled). + + + + + + vacuum_insert_score double precision + + + Vacuum insert component score. Scores greater than or equal to + 1.0 indicate the table will be vacuumed (unless + autovacuum is disabled). + + + + + + analyze_score double precision + + + Analyze component score. Scores greater than or equal to + 1.0 indicate the table will be analyzed (unless + autovacuum is disabled). + + + + +
+
+ <structname>pg_stat_all_indexes</structname> diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index eba25aa3e4d..5c2f2977965 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -795,6 +795,21 @@ 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 + 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 1be1ba8a25f..c6c601dd3ad 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" @@ -111,6 +112,7 @@ #include "utils/syscache.h" #include "utils/timeout.h" #include "utils/timestamp.h" +#include "utils/tuplestore.h" #include "utils/wait_event.h" @@ -3623,3 +3625,71 @@ 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[7]; + bool nulls[7] = {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); + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls); + } + table_endscan(scan); + table_close(rel, AccessShareLock); + + return (Datum) 0; +} diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index bd177aebfcb..0de3bb52eb2 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5667,6 +5667,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 => 'v', proparallel => 'u', prorettype => 'record', proargtypes => '', + proallargtypes => '{oid,float8,float8,float8,float8,float8,float8}', + proargmodes => '{o,o,o,o,o,o,o}', + proargnames => '{oid,score,xid_score,mxid_score,vacuum_score,vacuum_insert_score,analyze_score}', + 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 81a73c426d2..b167e8d3cab 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1860,6 +1860,18 @@ 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 + FROM ((pg_stat_get_autovacuum_scores() s(oid, score, xid_score, mxid_score, vacuum_score, vacuum_insert_score, analyze_score) + 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, -- 2.50.1 (Apple Git-155) --VsQ7gtq8Z1iRN55c--