From 302d369c81d269725a325fa72e820b42156aef31 Mon Sep 17 00:00:00 2001 From: TatsuyaKawata Date: Sat, 22 Nov 2025 01:19:33 +0900 Subject: [PATCH v10] Add dead items memory usage to VACUUM (VERBOSE) and autovacuum logs. This commit adds the total memory allocated during vacuum, the number of times the dead items storage was reset, and the configured memory limit. This helps users understand how much memory VACUUM required, and such information can be used to avoid multiple index scans. 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 | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 30778a15639..3ff1f1fddfd 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() && @@ -767,6 +770,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; @@ -864,6 +869,14 @@ heap_vacuum_rel(Relation rel, const VacuumParams params, */ lazy_scan_heap(vacrel); + /* + * Save dead items max_bytes and update the memory usage statistics before + * cleanup, they are freed in parallel vacuum cases during + * dead_items_cleanup(). + */ + dead_items_max_bytes = vacrel->dead_items_info->max_bytes; + vacrel->total_dead_items_bytes += TidStoreMemoryUsage(vacrel->dead_items); + /* * Free resources managed by dead_items_alloc. This ends parallel mode in * passing when necessary. @@ -1167,6 +1180,22 @@ 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 reset the + * collected dead items, so the counter is non-zero if at least + * one dead items are collected, even if index vacuuming is + * disabled. + */ + appendStringInfo(&buf, + ngettext("memory usage: %.2f MB in total, with dead item storage reset %d time (limit was %.2f MB)\n", + "memory usage: %.2f MB in total, with dead item storage reset %d times (limit was %.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, @@ -3617,6 +3646,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