From 1a53794326472848eae57fd442d1779402e1e1d8 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Wed, 8 Nov 2023 13:43:34 -0500 Subject: [PATCH v1 1/9] Make LVRelState accessible to stats Relocate LVRelState and VacErrPhase to vacuum.h so that pgstat_report_vacuum() can access members of LVRelState directly. This is to prepare for future commits which will add additional LVRelState members to be accumulated into the stats system by pgstat_report_vacuum(). --- src/backend/access/heap/vacuumlazy.c | 100 +------------------ src/backend/commands/vacuum.c | 1 - src/backend/utils/activity/pgstat_relation.c | 20 +++- src/include/commands/vacuum.h | 87 ++++++++++++++++ src/include/pgstat.h | 4 +- 5 files changed, 107 insertions(+), 105 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 6985d299b2..0b86c9d4ea 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -127,90 +127,6 @@ */ #define ParallelVacuumIsActive(vacrel) ((vacrel)->pvs != NULL) -/* Phases of vacuum during which we report error context. */ -typedef enum -{ - VACUUM_ERRCB_PHASE_UNKNOWN, - VACUUM_ERRCB_PHASE_SCAN_HEAP, - VACUUM_ERRCB_PHASE_VACUUM_INDEX, - VACUUM_ERRCB_PHASE_VACUUM_HEAP, - VACUUM_ERRCB_PHASE_INDEX_CLEANUP, - VACUUM_ERRCB_PHASE_TRUNCATE, -} VacErrPhase; - -typedef struct LVRelState -{ - /* Target heap relation and its indexes */ - Relation rel; - Relation *indrels; - int nindexes; - - /* Buffer access strategy and parallel vacuum state */ - BufferAccessStrategy bstrategy; - ParallelVacuumState *pvs; - - /* Aggressive VACUUM? (must set relfrozenxid >= FreezeLimit) */ - bool aggressive; - /* Use visibility map to skip? (disabled by DISABLE_PAGE_SKIPPING) */ - bool skipwithvm; - /* Consider index vacuuming bypass optimization? */ - bool consider_bypass_optimization; - - /* Doing index vacuuming, index cleanup, rel truncation? */ - bool do_index_vacuuming; - bool do_index_cleanup; - bool do_rel_truncate; - - /* VACUUM operation's cutoffs for freezing and pruning */ - struct VacuumCutoffs cutoffs; - GlobalVisState *vistest; - /* Tracks oldest extant XID/MXID for setting relfrozenxid/relminmxid */ - TransactionId NewRelfrozenXid; - MultiXactId NewRelminMxid; - bool skippedallvis; - - /* Error reporting state */ - char *dbname; - char *relnamespace; - char *relname; - char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ - OffsetNumber offnum; /* used only for heap operations */ - VacErrPhase phase; - bool verbose; /* VACUUM VERBOSE? */ - - /* - * dead_items stores TIDs whose index tuples are deleted by index - * vacuuming. Each TID points to an LP_DEAD line pointer from a heap page - * that has been processed by lazy_scan_prune. Also needed by - * lazy_vacuum_heap_rel, which marks the same LP_DEAD line pointers as - * LP_UNUSED during second heap pass. - */ - VacDeadItems *dead_items; /* TIDs whose index tuples we'll delete */ - BlockNumber rel_pages; /* total number of pages */ - BlockNumber scanned_pages; /* # pages examined (not skipped via VM) */ - BlockNumber removed_pages; /* # pages removed by relation truncation */ - BlockNumber frozen_pages; /* # pages with newly frozen tuples */ - BlockNumber lpdead_item_pages; /* # pages with LP_DEAD items */ - BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ - BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ - - /* Statistics output by us, for table */ - double new_rel_tuples; /* new estimated total # of tuples */ - double new_live_tuples; /* new estimated total # of live tuples */ - /* Statistics output by index AMs */ - IndexBulkDeleteResult **indstats; - - /* Instrumentation counters */ - int num_index_scans; - /* Counters that follow are only for scanned_pages */ - int64 tuples_deleted; /* # deleted from table */ - int64 tuples_frozen; /* # newly frozen */ - int64 lpdead_items; /* # deleted from indexes */ - int64 live_tuples; /* # live tuples remaining */ - int64 recently_dead_tuples; /* # dead, but not yet removable */ - int64 missed_dead_tuples; /* # removable, but not removed */ -} LVRelState; /* * State returned by lazy_scan_prune() @@ -583,21 +499,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->NewRelfrozenXid, vacrel->NewRelminMxid, &frozenxid_updated, &minmulti_updated, false); - /* - * Report results to the cumulative stats system, too. - * - * Deliberately avoid telling the stats system about LP_DEAD items that - * remain in the table due to VACUUM bypassing index and heap vacuuming. - * ANALYZE will consider the remaining LP_DEAD items to be dead "tuples". - * It seems like a good idea to err on the side of not vacuuming again too - * soon in cases where the failsafe prevented significant amounts of heap - * vacuuming. - */ + /* Report results to the cumulative stats system, too. */ pgstat_report_vacuum(RelationGetRelid(rel), - rel->rd_rel->relisshared, - Max(vacrel->new_live_tuples, 0), - vacrel->recently_dead_tuples + - vacrel->missed_dead_tuples); + rel->rd_rel->relisshared, vacrel); pgstat_progress_end_command(); if (instrument) diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 8bdbee6841..823fb67010 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -59,7 +59,6 @@ #include "utils/guc_hooks.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" -#include "utils/snapmgr.h" #include "utils/syscache.h" diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index f5d726e292..bd92380a68 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -207,10 +207,12 @@ pgstat_drop_relation(Relation rel) /* * Report that the table was just vacuumed and flush IO statistics. + * + * vacrel is an input parameter only and will not be modified by + * pgstat_report_vacuum(). */ void -pgstat_report_vacuum(Oid tableoid, bool shared, - PgStat_Counter livetuples, PgStat_Counter deadtuples) +pgstat_report_vacuum(Oid tableoid, bool shared, LVRelState *vacrel) { PgStat_EntryRef *entry_ref; PgStatShared_Relation *shtabentry; @@ -231,8 +233,18 @@ pgstat_report_vacuum(Oid tableoid, bool shared, shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats; tabentry = &shtabentry->stats; - tabentry->live_tuples = livetuples; - tabentry->dead_tuples = deadtuples; + tabentry->live_tuples = Max(vacrel->new_live_tuples, 0); + + /* + * Deliberately avoid telling the stats system about LP_DEAD items that + * remain in the table due to VACUUM bypassing index and heap vacuuming. + * ANALYZE will consider the remaining LP_DEAD items to be dead "tuples". + * It seems like a good idea to err on the side of not vacuuming again too + * soon in cases where the failsafe prevented significant amounts of heap + * vacuuming. + */ + tabentry->dead_tuples = vacrel->recently_dead_tuples + + vacrel->missed_dead_tuples; /* * It is quite possible that a non-aggressive VACUUM ended up skipping diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 4af02940c5..f48c4ab95a 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -24,6 +24,7 @@ #include "storage/buf.h" #include "storage/lock.h" #include "utils/relcache.h" +#include "utils/snapmgr.h" /* * Flags for amparallelvacuumoptions to control the participation of bulkdelete @@ -175,6 +176,7 @@ typedef struct VacAttrStats int rowstride; } VacAttrStats; + /* flag bits for VacuumParams->options */ #define VACOPT_VACUUM 0x01 /* do VACUUM */ #define VACOPT_ANALYZE 0x02 /* do ANALYZE */ @@ -291,6 +293,91 @@ typedef struct VacDeadItems #define MAXDEADITEMS(avail_mem) \ (((avail_mem) - offsetof(VacDeadItems, items)) / sizeof(ItemPointerData)) +/* Phases of vacuum during which we report error context. */ +typedef enum +{ + VACUUM_ERRCB_PHASE_UNKNOWN, + VACUUM_ERRCB_PHASE_SCAN_HEAP, + VACUUM_ERRCB_PHASE_VACUUM_INDEX, + VACUUM_ERRCB_PHASE_VACUUM_HEAP, + VACUUM_ERRCB_PHASE_INDEX_CLEANUP, + VACUUM_ERRCB_PHASE_TRUNCATE, +} VacErrPhase; + +typedef struct LVRelState +{ + /* Target heap relation and its indexes */ + Relation rel; + Relation *indrels; + int nindexes; + + /* Buffer access strategy and parallel vacuum state */ + BufferAccessStrategy bstrategy; + ParallelVacuumState *pvs; + + /* Aggressive VACUUM? (must set relfrozenxid >= FreezeLimit) */ + bool aggressive; + /* Use visibility map to skip? (disabled by DISABLE_PAGE_SKIPPING) */ + bool skipwithvm; + /* Consider index vacuuming bypass optimization? */ + bool consider_bypass_optimization; + + /* Doing index vacuuming, index cleanup, rel truncation? */ + bool do_index_vacuuming; + bool do_index_cleanup; + bool do_rel_truncate; + + /* VACUUM operation's cutoffs for freezing and pruning */ + struct VacuumCutoffs cutoffs; + GlobalVisState *vistest; + /* Tracks oldest extant XID/MXID for setting relfrozenxid/relminmxid */ + TransactionId NewRelfrozenXid; + MultiXactId NewRelminMxid; + bool skippedallvis; + + /* Error reporting state */ + char *dbname; + char *relnamespace; + char *relname; + char *indname; /* Current index name */ + BlockNumber blkno; /* used only for heap operations */ + OffsetNumber offnum; /* used only for heap operations */ + VacErrPhase phase; + bool verbose; /* VACUUM VERBOSE? */ + + /* + * dead_items stores TIDs whose index tuples are deleted by index + * vacuuming. Each TID points to an LP_DEAD line pointer from a heap page + * that has been processed by lazy_scan_prune. Also needed by + * lazy_vacuum_heap_rel, which marks the same LP_DEAD line pointers as + * LP_UNUSED during second heap pass. + */ + VacDeadItems *dead_items; /* TIDs whose index tuples we'll delete */ + BlockNumber rel_pages; /* total number of pages */ + BlockNumber scanned_pages; /* # pages examined (not skipped via VM) */ + BlockNumber removed_pages; /* # pages removed by relation truncation */ + BlockNumber frozen_pages; /* # pages with newly frozen tuples */ + BlockNumber lpdead_item_pages; /* # pages with LP_DEAD items */ + BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ + BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ + + /* Statistics output by us, for table */ + double new_rel_tuples; /* new estimated total # of tuples */ + double new_live_tuples; /* new estimated total # of live tuples */ + /* Statistics output by index AMs */ + IndexBulkDeleteResult **indstats; + + /* Instrumentation counters */ + int num_index_scans; + /* Counters that follow are only for scanned_pages */ + int64 tuples_deleted; /* # deleted from table */ + int64 tuples_frozen; /* # newly frozen */ + int64 lpdead_items; /* # deleted from indexes */ + int64 live_tuples; /* # live tuples remaining */ + int64 recently_dead_tuples; /* # dead, but not yet removable */ + int64 missed_dead_tuples; /* # removable, but not removed */ +} LVRelState; + /* GUC parameters */ extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for PostGIS */ extern PGDLLIMPORT int vacuum_freeze_min_age; diff --git a/src/include/pgstat.h b/src/include/pgstat.h index f95d8db0c4..5e84deec9a 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -11,6 +11,7 @@ #ifndef PGSTAT_H #define PGSTAT_H +#include "commands/vacuum.h" #include "datatype/timestamp.h" #include "portability/instr_time.h" #include "postmaster/pgarch.h" /* for MAX_XFN_CHARS */ @@ -587,8 +588,7 @@ extern void pgstat_init_relation(Relation rel); extern void pgstat_assoc_relation(Relation rel); extern void pgstat_unlink_relation(Relation rel); -extern void pgstat_report_vacuum(Oid tableoid, bool shared, - PgStat_Counter livetuples, PgStat_Counter deadtuples); +extern void pgstat_report_vacuum(Oid tableoid, bool shared, LVRelState *vacrel); extern void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, bool resetcounter); -- 2.37.2