From 7e0f1583ab0745334e473c4e5d69cae17ff0533c Mon Sep 17 00:00:00 2001 From: TatsuyaKawata Date: Sat, 22 Nov 2025 01:19:33 +0900 Subject: [PATCH v7] Add memory usage reporting to VACUUM VERBOSE This patch enhances VACUUM VERBOSE to report the memory usage of dead-items tracking. It shows the total memory consumed across all resets, the number of times the dead-item storage was reset, and the configured memory limit. The counter num_dead_items_resets increases when we collect enough dead items to trigger index vacuuming. The reporting includes proper handling of parallel vacuum cases where dead_items_info may be freed. Reviewed-by: Masahiko Sawada Reviewed-by: Chao Li Discussion: https://www.postgresql.org/message-id/flat/CAHza6qcPitBCkyiKJosDTt3bmxMvzZOTONoebwCkBZrr3rk65Q%40mail.gmail.com --- src/backend/access/heap/vacuumlazy.c | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 65bb0568a86..e469bf26d99 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -347,6 +347,8 @@ typedef struct LVRelState /* Instrumentation counters */ int num_index_scans; + int num_dead_items_resets; + Size total_dead_items_bytes; /* Counters that follow are only for scanned_pages */ int64 tuples_deleted; /* # deleted from table */ int64 tuples_frozen; /* # newly frozen */ @@ -645,6 +647,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, BufferUsage startbufferusage = pgBufferUsage; ErrorContextCallback errcallback; char **indnames = NULL; + Size dead_items_max_bytes = 0; verbose = (params.options & VACOPT_VERBOSE) != 0; instrument = (verbose || (AmAutoVacuumWorkerProcess() && @@ -759,6 +762,8 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, /* Initialize remaining counters (be tidy) */ vacrel->num_index_scans = 0; + vacrel->num_dead_items_resets = 0; + vacrel->total_dead_items_bytes = 0; vacrel->tuples_deleted = 0; vacrel->tuples_frozen = 0; vacrel->lpdead_items = 0; @@ -850,6 +855,13 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, */ lazy_scan_heap(vacrel); + /* + * Save dead items max_bytes before cleanup for reporting the memory usage + * as the dead_items_info is freed in parallel vacuum cases during + * dead_items_cleanup(). + */ + dead_items_max_bytes = vacrel->dead_items_info->max_bytes; + /* * Free resources managed by dead_items_alloc. This ends parallel mode in * passing when necessary. @@ -1154,6 +1166,23 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, walusage.wal_bytes, walusage.wal_fpi_bytes, walusage.wal_buffers_full); + + /* + * Report the dead-items memory usage. + * + * The num_dead_items_resets counter increases when we collect + * enough dead items to trigger index vacuuming, either because + * we've run out of available space or reached the end of the + * table. Note that this counter may be non-zero even when index + * vacuuming is disabled. + */ + appendStringInfo(&buf, + ngettext("memory usage: %.2f MB in total, with dead-item storage reset %d time (memory allocated: %.2f MB)\n", + "memory usage: %.2f MB in total, with dead-item storage reset %d times (memory allocated: %.2f MB)\n", + vacrel->num_dead_items_resets), + (double) vacrel->total_dead_items_bytes / (1024 * 1024), + vacrel->num_dead_items_resets, + (double) dead_items_max_bytes / (1024 * 1024)); appendStringInfo(&buf, _("system usage: %s"), pg_rusage_show(&ru0)); ereport(verbose ? INFO : LOG, @@ -1540,6 +1569,12 @@ lazy_scan_heap(LVRelState *vacrel) if (vacrel->dead_items_info->num_items > 0) lazy_vacuum(vacrel); + /* + * Account for initial dead_items memory if nothing was collected. + */ + if (vacrel->dead_items_info->num_items == 0 && vacrel->num_dead_items_resets == 0) + vacrel->total_dead_items_bytes += TidStoreMemoryUsage(vacrel->dead_items); + /* * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. @@ -3603,6 +3638,10 @@ dead_items_add(LVRelState *vacrel, BlockNumber blkno, OffsetNumber *offsets, static void dead_items_reset(LVRelState *vacrel) { + /* Update statistics for dead items */ + vacrel->num_dead_items_resets++; + vacrel->total_dead_items_bytes += TidStoreMemoryUsage(vacrel->dead_items); + if (ParallelVacuumIsActive(vacrel)) { parallel_vacuum_reset_dead_items(vacrel->pvs); -- 2.34.1