From 12355fe2b0d1ac5f1d16ac3e1e5860bb4f641a2d Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Fri, 8 Aug 2025 07:12:51 +0000 Subject: [PATCH v1 07/10] Adding vacuum_count to pg_stat_backend Adding per backend number of manual vacuums triggered. XXX: Bump catversion. --- doc/src/sgml/monitoring.sgml | 9 +++++++++ src/backend/catalog/system_views.sql | 1 + src/backend/utils/activity/pgstat_backend.c | 4 ++++ src/backend/utils/activity/pgstat_relation.c | 1 + src/backend/utils/adt/pgstatfuncs.c | 3 ++- src/include/catalog/pg_proc.dat | 6 +++--- src/include/pgstat.h | 3 +++ src/test/regress/expected/rules.out | 3 ++- src/test/regress/expected/vacuum.out | 15 +++++++++++++++ src/test/regress/sql/vacuum.sql | 11 +++++++++++ 10 files changed, 51 insertions(+), 5 deletions(-) 14.5% doc/src/sgml/ 8.0% src/backend/utils/activity/ 7.2% src/backend/utils/adt/ 15.8% src/include/catalog/ 5.9% src/include/ 30.4% src/test/regress/expected/ 16.5% src/test/regress/sql/ diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index a6313a32299..1b3154d5326 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1267,6 +1267,15 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + vacuum_count bigint + + + The number of manual vacuums triggered (not counting VACUUM FULL). + + + stats_reset timestamp with time zone diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index d87fd38b8b2..6257bce86a1 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -919,6 +919,7 @@ CREATE VIEW pg_stat_backend AS S.idx_tup_fetch, S.idx_scan, S.idx_tup_read, + S.vacuum_count, S.stats_reset FROM pg_stat_get_backend_statistics(NULL) AS S; diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c index df072cb082f..58386662359 100644 --- a/src/backend/utils/activity/pgstat_backend.c +++ b/src/backend/utils/activity/pgstat_backend.c @@ -291,6 +291,7 @@ pgstat_flush_backend_entry_rel(PgStat_EntryRef *entry_ref) BACKENDREL_ACC(idx_tup_fetch); BACKENDREL_ACC(idx_scan); BACKENDREL_ACC(idx_tup_read); + BACKENDREL_ACC(vacuum_count); #undef BACKENDREL_ACC /* @@ -473,6 +474,9 @@ PGSTAT_COUNT_BACKEND_FUNC(idx_tup_fetch) /* pgstat_count_backend_rel_idx_scan */ PGSTAT_COUNT_BACKEND_FUNC(idx_scan) +/* pgstat_count_backend_rel_vacuum_count */ +PGSTAT_COUNT_BACKEND_FUNC(vacuum_count) + void pgstat_count_backend_rel_idx_tup_read(PgStat_Counter n) { diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 69df741cbf6..555f0815454 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -258,6 +258,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared, tabentry->last_vacuum_time = ts; tabentry->vacuum_count++; tabentry->total_vacuum_time += elapsedtime; + pgstat_count_backend_rel_vacuum_count(); } pgstat_unlock_entry(entry_ref); diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 99486851281..bff5bfc0538 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -691,7 +691,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) Datum pg_stat_get_backend_statistics(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_BACKEND_STATS_COLS 7 +#define PG_STAT_GET_BACKEND_STATS_COLS 8 int num_backends = pgstat_fetch_stat_numbackends(); int curr_backend; int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); @@ -730,6 +730,7 @@ pg_stat_get_backend_statistics(PG_FUNCTION_ARGS) values[i++] = Int64GetDatum(backend_stats->idx_tup_fetch); values[i++] = Int64GetDatum(backend_stats->idx_scan); values[i++] = Int64GetDatum(backend_stats->idx_tup_read); + values[i++] = Int64GetDatum(backend_stats->vacuum_count); if (backend_stats->stat_reset_timestamp != 0) values[i] = TimestampTzGetDatum(backend_stats->stat_reset_timestamp); diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index bb5608f492e..aae43548923 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5646,9 +5646,9 @@ proname => 'pg_stat_get_backend_statistics', prorows => '100', proisstrict => 'f', proretset => 't', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => 'int4', - proallargtypes => '{int4,int4,int8,int8,int8,int8,int8,timestamptz}', - proargmodes => '{i,o,o,o,o,o,o,o}', - proargnames => '{pid,pid,seq_scan,seq_tup_read,idx_tup_fetch,idx_scan,idx_tup_read,stats_reset}', + proallargtypes => '{int4,int4,int8,int8,int8,int8,int8,int8,timestamptz}', + proargmodes => '{i,o,o,o,o,o,o,o,o}', + proargnames => '{pid,pid,seq_scan,seq_tup_read,idx_tup_fetch,idx_scan,idx_tup_read,vacuum_count,stats_reset}', prosrc => 'pg_stat_get_backend_statistics' }, { oid => '6318', descr => 'describe wait events', proname => 'pg_get_wait_events', procost => '10', prorows => '250', diff --git a/src/include/pgstat.h b/src/include/pgstat.h index f26b9e12567..558bfd3c123 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -495,6 +495,7 @@ typedef struct PgStat_Backend PgStat_Counter idx_tup_fetch; PgStat_Counter idx_scan; PgStat_Counter idx_tup_read; + PgStat_Counter vacuum_count; } PgStat_Backend; typedef struct PgStat_BackendRelPending @@ -504,6 +505,7 @@ typedef struct PgStat_BackendRelPending PgStat_Counter idx_tup_fetch; PgStat_Counter idx_scan; PgStat_Counter idx_tup_read; + PgStat_Counter vacuum_count; } PgStat_BackendRelPending; /* --------- @@ -588,6 +590,7 @@ extern void pgstat_count_backend_rel_seq_tup_read(void); extern void pgstat_count_backend_rel_idx_tup_fetch(void); extern void pgstat_count_backend_rel_idx_scan(void); extern void pgstat_count_backend_rel_idx_tup_read(PgStat_Counter n); +extern void pgstat_count_backend_rel_vacuum_count(void); /* * Functions in pgstat_bgwriter.c diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 2da8a8122f1..7df7fe37ed4 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1853,8 +1853,9 @@ pg_stat_backend| SELECT pid, idx_tup_fetch, idx_scan, idx_tup_read, + vacuum_count, stats_reset - FROM pg_stat_get_backend_statistics(NULL::integer) s(pid, seq_scan, seq_tup_read, idx_tup_fetch, idx_scan, idx_tup_read, stats_reset); + FROM pg_stat_get_backend_statistics(NULL::integer) s(pid, seq_scan, seq_tup_read, idx_tup_fetch, idx_scan, idx_tup_read, vacuum_count, stats_reset); 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, diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 0abcc99989e..b7ab929084f 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -469,6 +469,7 @@ CREATE VIEW vac_option_tab_counts AS LEFT JOIN pg_class c ON s.relid = c.reltoastrelid WHERE c.relname = 'vac_option_tab' OR s.relname = 'vac_option_tab' ORDER BY rel; +SELECT vacuum_count AS vacuum_count_before FROM pg_stat_backend WHERE pid = pg_backend_pid() \gset VACUUM (PROCESS_TOAST TRUE) vac_option_tab; SELECT * FROM vac_option_tab_counts; rel | vacuum_count @@ -497,6 +498,20 @@ SELECT * FROM vac_option_tab_counts; toast | 2 (2 rows) +-- ensure pending stats are flushed +SELECT pg_stat_force_next_flush(); + pg_stat_force_next_flush +-------------------------- + +(1 row) + +SELECT vacuum_count AS vacuum_count_after FROM pg_stat_backend WHERE pid = pg_backend_pid() \gset +SELECT :vacuum_count_after > :vacuum_count_before; + ?column? +---------- + t +(1 row) + -- Nothing is processed. VACUUM (PROCESS_MAIN FALSE, PROCESS_TOAST FALSE) vac_option_tab; SELECT * FROM vac_option_tab_counts; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index a72bdb5b619..b1bcd442c13 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -364,6 +364,9 @@ CREATE VIEW vac_option_tab_counts AS LEFT JOIN pg_class c ON s.relid = c.reltoastrelid WHERE c.relname = 'vac_option_tab' OR s.relname = 'vac_option_tab' ORDER BY rel; + +SELECT vacuum_count AS vacuum_count_before FROM pg_stat_backend WHERE pid = pg_backend_pid() \gset + VACUUM (PROCESS_TOAST TRUE) vac_option_tab; SELECT * FROM vac_option_tab_counts; VACUUM (PROCESS_TOAST FALSE) vac_option_tab; @@ -374,6 +377,14 @@ VACUUM (PROCESS_TOAST FALSE, FULL) vac_option_tab; -- error -- Only the toast table is processed. VACUUM (PROCESS_MAIN FALSE) vac_option_tab; SELECT * FROM vac_option_tab_counts; + +-- ensure pending stats are flushed +SELECT pg_stat_force_next_flush(); + +SELECT vacuum_count AS vacuum_count_after FROM pg_stat_backend WHERE pid = pg_backend_pid() \gset + +SELECT :vacuum_count_after > :vacuum_count_before; + -- Nothing is processed. VACUUM (PROCESS_MAIN FALSE, PROCESS_TOAST FALSE) vac_option_tab; SELECT * FROM vac_option_tab_counts; -- 2.34.1