From: Masahiko Sawada Date: Thu, 19 Mar 2026 22:01:47 +0000 (-0700) Subject: Add parallel vacuum worker usage to VACUUM (VERBOSE) and autovacuum logs. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=adcdbe93860b16a069c6834062e56e731c54a1a1;p=thirdparty%2Fpostgresql.git Add parallel vacuum worker usage to VACUUM (VERBOSE) and autovacuum logs. This commit adds both the number of parallel workers planned and the number of parallel workers actually launched to the output of VACUUM (VERBOSE) and autovacuum logs. Previously, this information was only reported as an INFO message during VACUUM (VERBOSE), which meant it was not included in autovacuum logs in practice. Although autovacuum does not yet support parallel vacuum, a subsequent patch will enable it and utilize these logs in its regression tests. This change also improves observability by making it easier to verify if parallel vacuum is utilizing the expected number of workers. Author: Daniil Davydov <3danissimo@gmail.com> Reviewed-by: Masahiko Sawada Reviewed-by: Sami Imseih Discussion: https://postgr.es/m/CACG=ezZOrNsuLoETLD1gAswZMuH2nGGq7Ogcc0QOE5hhWaw=cw@mail.gmail.com --- diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 82c5b28e0ad..c57432670e7 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -343,6 +343,13 @@ typedef struct LVRelState int num_index_scans; int num_dead_items_resets; Size total_dead_items_bytes; + + /* + * Total number of planned and actually launched parallel workers for + * index vacuuming and index cleanup. + */ + PVWorkerUsage worker_usage; + /* Counters that follow are only for scanned_pages */ int64 tuples_deleted; /* # deleted from table */ int64 tuples_frozen; /* # newly frozen */ @@ -781,6 +788,11 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, vacrel->new_all_visible_all_frozen_pages = 0; vacrel->new_all_frozen_pages = 0; + vacrel->worker_usage.vacuum.nlaunched = 0; + vacrel->worker_usage.vacuum.nplanned = 0; + vacrel->worker_usage.cleanup.nlaunched = 0; + vacrel->worker_usage.cleanup.nplanned = 0; + /* * Get cutoffs that determine which deleted tuples are considered DEAD, * not just RECENTLY_DEAD, and which XIDs/MXIDs to freeze. Then determine @@ -1123,6 +1135,19 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, orig_rel_pages == 0 ? 100.0 : 100.0 * vacrel->lpdead_item_pages / orig_rel_pages, vacrel->lpdead_items); + + if (vacrel->worker_usage.vacuum.nplanned > 0) + appendStringInfo(&buf, + _("parallel workers: index vacuum: %d planned, %d launched in total\n"), + vacrel->worker_usage.vacuum.nplanned, + vacrel->worker_usage.vacuum.nlaunched); + + if (vacrel->worker_usage.cleanup.nplanned > 0) + appendStringInfo(&buf, + _("parallel workers: index cleanup: %d planned, %d launched\n"), + vacrel->worker_usage.cleanup.nplanned, + vacrel->worker_usage.cleanup.nlaunched); + for (int i = 0; i < vacrel->nindexes; i++) { IndexBulkDeleteResult *istat = vacrel->indstats[i]; @@ -2669,7 +2694,8 @@ lazy_vacuum_all_indexes(LVRelState *vacrel) { /* Outsource everything to parallel variant */ parallel_vacuum_bulkdel_all_indexes(vacrel->pvs, old_live_tuples, - vacrel->num_index_scans); + vacrel->num_index_scans, + &(vacrel->worker_usage.vacuum)); /* * Do a postcheck to consider applying wraparound failsafe now. Note @@ -3103,7 +3129,8 @@ lazy_cleanup_all_indexes(LVRelState *vacrel) /* Outsource everything to parallel variant */ parallel_vacuum_cleanup_all_indexes(vacrel->pvs, reltuples, vacrel->num_index_scans, - estimated_count); + estimated_count, + &(vacrel->worker_usage.cleanup)); } /* Reset the progress counters */ diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 279108ca89f..77834b96a21 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -225,7 +225,7 @@ struct ParallelVacuumState static int parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int nrequested, bool *will_parallel_vacuum); static void parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scans, - bool vacuum); + bool vacuum, PVWorkerStats *wstats); static void parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs); static void parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs); static void parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, @@ -499,7 +499,7 @@ parallel_vacuum_reset_dead_items(ParallelVacuumState *pvs) */ void parallel_vacuum_bulkdel_all_indexes(ParallelVacuumState *pvs, long num_table_tuples, - int num_index_scans) + int num_index_scans, PVWorkerStats *wstats) { Assert(!IsParallelWorker()); @@ -510,7 +510,7 @@ parallel_vacuum_bulkdel_all_indexes(ParallelVacuumState *pvs, long num_table_tup pvs->shared->reltuples = num_table_tuples; pvs->shared->estimated_count = true; - parallel_vacuum_process_all_indexes(pvs, num_index_scans, true); + parallel_vacuum_process_all_indexes(pvs, num_index_scans, true, wstats); } /* @@ -518,7 +518,8 @@ parallel_vacuum_bulkdel_all_indexes(ParallelVacuumState *pvs, long num_table_tup */ void parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, long num_table_tuples, - int num_index_scans, bool estimated_count) + int num_index_scans, bool estimated_count, + PVWorkerStats *wstats) { Assert(!IsParallelWorker()); @@ -530,7 +531,7 @@ parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, long num_table_tup pvs->shared->reltuples = num_table_tuples; pvs->shared->estimated_count = estimated_count; - parallel_vacuum_process_all_indexes(pvs, num_index_scans, false); + parallel_vacuum_process_all_indexes(pvs, num_index_scans, false, wstats); } /* @@ -607,10 +608,12 @@ parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int nrequested, /* * Perform index vacuum or index cleanup with parallel workers. This function * must be used by the parallel vacuum leader process. + * + * If wstats is not NULL, the parallel worker statistics are updated. */ static void parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scans, - bool vacuum) + bool vacuum, PVWorkerStats *wstats) { int nworkers; PVIndVacStatus new_status; @@ -647,6 +650,10 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan */ nworkers = Min(nworkers, pvs->pcxt->nworkers); + /* Update the statistics, if we asked to */ + if (wstats != NULL && nworkers > 0) + wstats->nplanned += nworkers; + /* * Set index vacuum status and mark whether parallel vacuum worker can * process it. @@ -703,6 +710,10 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan /* Enable shared cost balance for leader backend */ VacuumSharedCostBalance = &(pvs->shared->cost_balance); VacuumActiveNWorkers = &(pvs->shared->active_nworkers); + + /* Update the statistics, if we asked to */ + if (wstats != NULL) + wstats->nlaunched += pvs->pcxt->nworkers_launched; } if (vacuum) diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index e885a4b9c77..953a506181e 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -300,6 +300,28 @@ typedef struct VacDeadItemsInfo int64 num_items; /* current # of entries */ } VacDeadItemsInfo; +/* + * Statistics for parallel vacuum workers (planned vs. actual) + */ +typedef struct PVWorkerStats +{ + /* Number of parallel workers planned to launch */ + int nplanned; + + /* Number of parallel workers that were successfully launched */ + int nlaunched; +} PVWorkerStats; + +/* + * PVWorkerUsage stores information about total number of launched and + * planned workers during parallel vacuum (both for index vacuum and cleanup). + */ +typedef struct PVWorkerUsage +{ + PVWorkerStats vacuum; + PVWorkerStats cleanup; +} PVWorkerUsage; + /* GUC parameters */ extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for PostGIS */ extern PGDLLIMPORT int vacuum_freeze_min_age; @@ -394,11 +416,13 @@ extern TidStore *parallel_vacuum_get_dead_items(ParallelVacuumState *pvs, extern void parallel_vacuum_reset_dead_items(ParallelVacuumState *pvs); extern void parallel_vacuum_bulkdel_all_indexes(ParallelVacuumState *pvs, long num_table_tuples, - int num_index_scans); + int num_index_scans, + PVWorkerStats *wstats); extern void parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, long num_table_tuples, int num_index_scans, - bool estimated_count); + bool estimated_count, + PVWorkerStats *wstats); extern void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc); /* in commands/analyze.c */ diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 4673eca9cd6..a4a2ed07816 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2090,6 +2090,8 @@ PVIndStats PVIndVacStatus PVOID PVShared +PVWorkerUsage +PVWorkerStats PX_Alias PX_Cipher PX_Combo