diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 0d038de1a23..6337d2a3d25 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -7685,8 +7685,10 @@ FROM pg_stat_get_backend_idset() AS backendid; Whenever VACUUM is running, the pg_stat_progress_vacuum view will contain - one row for each backend (including autovacuum worker processes) that is - currently vacuuming. The tables below describe the information + one row for each backend (including autovacuum worker processes and + parallel workers launched for + parallel vacuum) that is currently + vacuuming. The tables below describe the information that will be reported and provide information about how to interpret it. Progress for VACUUM FULL commands is reported via pg_stat_progress_repack, and is also visible via @@ -7944,10 +7946,61 @@ FROM pg_stat_get_backend_idset() AS backendid; + + + + current_index_relid oid + + + OID of the index currently being vacuumed, or 0 if none is. This + field is only valid when the phase is + vacuuming indexes or + cleaning up indexes. + + + + + + index_blks_total bigint + + + Total number of blocks in the index identified by + current_index_relid. Only B-tree indexes + report this; it is 0 for other index access methods, and when no index + scan is in progress. + + + + + + index_blks_done bigint + + + Number of blocks of that index scanned so far. It stops one block + short of index_blks_total, which counts the + index metapage, never scanned. + + + + + + During a parallel vacuum, the leader and each of its workers reports its + own row, all sharing the same relid. + Only phase, + current_index_relid, + index_blks_total and + index_blks_done are maintained on a worker row; + the remaining columns track command-level progress that only the leader + maintains. Use leader_pid in + pg_stat_activity + to tell the leader row from its worker rows. + + + VACUUM Phases diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 997d84a77b3..1f684b81f82 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -3038,17 +3038,27 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat, { IndexVacuumInfo ivinfo; LVSavedErrInfo saved_err_info; + const int reset_index[] = { + PROGRESS_VACUUM_CURRENT_INDEX_RELID, + PROGRESS_SCAN_BLOCKS_TOTAL, + PROGRESS_SCAN_BLOCKS_DONE + }; + const int64 reset_val[] = {(int64) InvalidOid, 0, 0}; ivinfo.index = indrel; ivinfo.heaprel = vacrel->rel; ivinfo.analyze_only = false; ivinfo.is_autovacuum = AmAutoVacuumWorkerProcess(); - ivinfo.report_progress = false; + ivinfo.report_progress = true; ivinfo.estimated_count = true; ivinfo.message_level = DEBUG2; ivinfo.num_heap_tuples = reltuples; ivinfo.strategy = vacrel->bstrategy; + /* Report which index we're currently processing */ + pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID, + (int64) RelationGetRelid(indrel)); + /* * Update error traceback information. * @@ -3070,6 +3080,8 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat, pfree(vacrel->indname); vacrel->indname = NULL; + pgstat_progress_update_multi_param(3, reset_index, reset_val); + return istat; } @@ -3089,18 +3101,28 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat, { IndexVacuumInfo ivinfo; LVSavedErrInfo saved_err_info; + const int reset_index[] = { + PROGRESS_VACUUM_CURRENT_INDEX_RELID, + PROGRESS_SCAN_BLOCKS_TOTAL, + PROGRESS_SCAN_BLOCKS_DONE + }; + const int64 reset_val[] = {(int64) InvalidOid, 0, 0}; ivinfo.index = indrel; ivinfo.heaprel = vacrel->rel; ivinfo.analyze_only = false; ivinfo.is_autovacuum = AmAutoVacuumWorkerProcess(); - ivinfo.report_progress = false; + ivinfo.report_progress = true; ivinfo.estimated_count = estimated_count; ivinfo.message_level = DEBUG2; ivinfo.num_heap_tuples = reltuples; ivinfo.strategy = vacrel->bstrategy; + /* Report which index we're currently processing */ + pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID, + (int64) RelationGetRelid(indrel)); + /* * Update error traceback information. * @@ -3120,6 +3142,8 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat, pfree(vacrel->indname); vacrel->indname = NULL; + pgstat_progress_update_multi_param(3, reset_index, reset_val); + return istat; } diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index ad340887f54..809b9c0f1e4 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1353,7 +1353,10 @@ CREATE VIEW pg_stat_progress_vacuum AS CASE S.param13 WHEN 1 THEN 'manual' WHEN 2 THEN 'autovacuum' WHEN 3 THEN 'autovacuum_wraparound' - ELSE NULL END AS started_by + ELSE NULL END AS started_by, + CAST(S.param14 AS oid) AS current_index_relid, + S.param16 AS index_blks_total, + S.param17 AS index_blks_done FROM pg_stat_get_progress_info('VACUUM') AS S LEFT JOIN pg_database D ON S.datid = D.oid; diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index da0ec3cc8ee..ac8ad6637b5 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -1115,6 +1115,17 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, IndexBulkDeleteResult *istat = NULL; IndexBulkDeleteResult *istat_res; IndexVacuumInfo ivinfo; + const int progress_index[] = { + PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_CURRENT_INDEX_RELID + }; + int64 progress_val[2]; + const int reset_index[] = { + PROGRESS_VACUUM_CURRENT_INDEX_RELID, + PROGRESS_SCAN_BLOCKS_TOTAL, + PROGRESS_SCAN_BLOCKS_DONE + }; + const int64 reset_val[] = {(int64) InvalidOid, 0, 0}; /* * Update the pointer to the corresponding bulk-deletion result if someone @@ -1127,7 +1138,7 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, ivinfo.heaprel = pvs->heaprel; ivinfo.analyze_only = false; ivinfo.is_autovacuum = pvs->shared->is_autovacuum; - ivinfo.report_progress = false; + ivinfo.report_progress = true; ivinfo.message_level = DEBUG2; ivinfo.estimated_count = pvs->shared->estimated_count; ivinfo.num_heap_tuples = pvs->shared->reltuples; @@ -1137,6 +1148,13 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, pvs->indname = pstrdup(RelationGetRelationName(indrel)); pvs->status = indstats->status; + /* Report the phase and the index we're about to process */ + progress_val[0] = (indstats->status == PARALLEL_INDVAC_STATUS_NEED_BULKDELETE) + ? PROGRESS_VACUUM_PHASE_VACUUM_INDEX + : PROGRESS_VACUUM_PHASE_INDEX_CLEANUP; + progress_val[1] = (int64) RelationGetRelid(indrel); + pgstat_progress_update_multi_param(2, progress_index, progress_val); + switch (indstats->status) { case PARALLEL_INDVAC_STATUS_NEED_BULKDELETE: @@ -1152,6 +1170,8 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, RelationGetRelationName(indrel)); } + pgstat_progress_update_multi_param(3, reset_index, reset_val); + /* * Copy the index bulk-deletion result returned from ambulkdelete and * amvacuumcleanup to the DSM segment if it's the first cycle because they @@ -1230,8 +1250,8 @@ parallel_vacuum_index_is_parallel_safe(Relation indrel, int num_index_scans, /* * Perform work within a launched parallel process. * - * Since parallel vacuum workers perform only index vacuum or index cleanup, - * we don't need to report progress information. + * Parallel vacuum workers perform only index vacuum or index cleanup; they + * report progress for the index they are processing. */ void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) @@ -1355,6 +1375,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) /* Prepare to track buffer usage during parallel execution */ InstrStartParallelQuery(); + /* Register this worker for vacuum progress reporting */ + pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, shared->relid); + /* Process indexes to perform vacuum/cleanup */ parallel_vacuum_process_safe_indexes(&pvs); @@ -1374,6 +1397,8 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) /* Pop the error context stack */ error_context_stack = errcallback.previous; + pgstat_progress_end_command(); + vac_close_indexes(nindexes, indrels, RowExclusiveLock); table_close(rel, ShareUpdateExclusiveLock); FreeAccessStrategy(pvs.bstrategy); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 6f3e526de96..7f7667f6179 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202609152 +#define CATALOG_VERSION_NO 202610021 #endif diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h index 2a12920c75f..bf91455eff9 100644 --- a/src/include/commands/progress.h +++ b/src/include/commands/progress.h @@ -31,6 +31,8 @@ #define PROGRESS_VACUUM_DELAY_TIME 10 #define PROGRESS_VACUUM_MODE 11 #define PROGRESS_VACUUM_STARTED_BY 12 +#define PROGRESS_VACUUM_CURRENT_INDEX_RELID 13 +/* 15 and 16 reserved for "block number" metrics */ /* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */ #define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1 diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 4a8cc759d7b..0addd043e68 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2214,7 +2214,10 @@ pg_stat_progress_vacuum| SELECT s.pid, WHEN 2 THEN 'autovacuum'::text WHEN 3 THEN 'autovacuum_wraparound'::text ELSE NULL::text - END AS started_by + END AS started_by, + (s.param14)::oid AS current_index_relid, + s.param16 AS index_blks_total, + s.param17 AS index_blks_done FROM (pg_stat_get_progress_info('VACUUM'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) LEFT JOIN pg_database d ON ((s.datid = d.oid))); pg_stat_recovery| SELECT promote_triggered,