diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index d9b07837831..c620d088204 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -413,7 +413,7 @@ typedef struct LVRelState int32 wraparound_failsafe_count; /* number of emergency vacuums to prevent anti-wraparound shutdown */ - ExtVacReport extVacReport; + PgStat_VacuumRelationCounts extVacReport; } LVRelState; @@ -525,7 +525,7 @@ extvac_stats_start(Relation rel, LVExtStatCounters *counters) */ static void extvac_stats_end(Relation rel, LVExtStatCounters *counters, - ExtVacReport *report) + PgStat_VacuumRelationCounts *report) { WalUsage walusage; BufferUsage bufusage; @@ -603,9 +603,9 @@ extvac_stats_start_idx(Relation rel, IndexBulkDeleteResult *stats, void extvac_stats_end_idx(Relation rel, IndexBulkDeleteResult *stats, - LVExtStatCountersIdx *counters, ExtVacReport *report) + LVExtStatCountersIdx *counters, PgStat_VacuumRelationCounts *report) { - memset(report, 0, sizeof(ExtVacReport)); + memset(report, 0, sizeof(PgStat_VacuumRelationCounts)); extvac_stats_end(rel, &counters->common, report); report->type = PGSTAT_EXTVAC_INDEX; @@ -1127,6 +1127,14 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * * We are ready to send vacuum statistics information for heap relations. */ + + pgstat_report_vacuum(RelationGetRelid(rel), + rel->rd_rel->relisshared, + Max(vacrel->new_live_tuples, 0), + vacrel->recently_dead_tuples + + vacrel->missed_dead_tuples, + starttime); + if(pgstat_track_vacuum_statistics) { /* Make generic extended vacuum stats report and @@ -1135,25 +1143,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, extvac_stats_end(vacrel->rel, &extVacCounters, &(vacrel->extVacReport)); accumulate_heap_vacuum_statistics(&extVacCounters, vacrel); - pgstat_report_vacuum(RelationGetRelid(rel), - rel->rd_rel->relisshared, - Max(vacrel->new_live_tuples, 0), - vacrel->recently_dead_tuples + - vacrel->missed_dead_tuples, - starttime, - &(vacrel->extVacReport)); + pgstat_report_tab_vacuum_extstats(vacrel->reloid, true, + &(vacrel->extVacReport)); } - else - { - pgstat_report_vacuum(RelationGetRelid(rel), - rel->rd_rel->relisshared, - Max(vacrel->new_live_tuples, 0), - vacrel->recently_dead_tuples + - vacrel->missed_dead_tuples, - starttime, - NULL); - } pgstat_progress_end_command(); @@ -3349,7 +3342,7 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat, IndexVacuumInfo ivinfo; LVSavedErrInfo saved_err_info; LVExtStatCountersIdx extVacCounters; - ExtVacReport extVacReport; + PgStat_VacuumRelationCounts extVacReport; /* Set initial statistics values to gather vacuum statistics for the index */ extvac_stats_start_idx(indrel, istat, &extVacCounters); @@ -3384,9 +3377,8 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat, { /* Make extended vacuum stats report for index */ extvac_stats_end_idx(indrel, istat, &extVacCounters, &extVacReport); - pgstat_report_vacuum(RelationGetRelid(indrel), - indrel->rd_rel->relisshared, - 0, 0, 0, &extVacReport); + pgstat_report_tab_vacuum_extstats(vacrel->indoid, true, + &extVacReport); } /* Revert to the previous phase information for error traceback */ @@ -3414,7 +3406,7 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat, IndexVacuumInfo ivinfo; LVSavedErrInfo saved_err_info; LVExtStatCountersIdx extVacCounters; - ExtVacReport extVacReport; + PgStat_VacuumRelationCounts extVacReport; /* Set initial statistics values to gather vacuum statistics for the index */ extvac_stats_start_idx(indrel, istat, &extVacCounters); @@ -3448,9 +3440,8 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat, { /* Make extended vacuum stats report for index */ extvac_stats_end_idx(indrel, istat, &extVacCounters, &extVacReport); - pgstat_report_vacuum(RelationGetRelid(indrel), - indrel->rd_rel->relisshared, - 0, 0, 0, &extVacReport); + pgstat_report_tab_vacuum_extstats(vacrel->indoid, true, + &extVacReport); } /* Revert to the previous phase information for error traceback */ diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index bd3554c0bfd..75c2e122bf2 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1873,6 +1873,7 @@ heap_drop_with_catalog(Oid relid) /* ensure that stats are dropped if transaction commits */ pgstat_drop_relation(rel); + pgstat_vacuum_relation_delete_pending_cb(RelationGetRelid(rel)); /* * Close relcache entry, but *keep* AccessExclusiveLock on the relation diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 739a92bdcc1..e4fa754aab4 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2327,6 +2327,7 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode) /* ensure that stats are dropped if transaction commits */ pgstat_drop_relation(userIndexRelation); + pgstat_vacuum_relation_delete_pending_cb(RelationGetRelid(userIndexRelation)); /* * Close and flush the index's relcache entry, to ensure relcache doesn't diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 5fbbcdaabb1..c4b910cd928 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -1789,6 +1789,7 @@ dropdb(const char *dbname, bool missing_ok, bool force) * Tell the cumulative stats system to forget it immediately, too. */ pgstat_drop_database(db_id); + pgstat_drop_vacuum_database(db_id); /* * Except for the deletion of the catalog row, subsequent actions are not diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 000388a565f..c2abed144c4 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -869,7 +869,7 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, IndexBulkDeleteResult *istat_res; IndexVacuumInfo ivinfo; LVExtStatCountersIdx extVacCounters; - ExtVacReport extVacReport; + PgStat_VacuumRelationCounts extVacReport; /* * Update the pointer to the corresponding bulk-deletion result if someone @@ -913,9 +913,8 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel, { /* Make extended vacuum stats report for index */ extvac_stats_end_idx(indrel, istat_res, &extVacCounters, &extVacReport); - pgstat_report_vacuum(RelationGetRelid(indrel), - indrel->rd_rel->relisshared, - 0, 0, 0, &extVacReport); + pgstat_report_tab_vacuum_extstats(RelationGetRelid(indrel), true, + &extVacReport); } /* diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile index 9c2443e1ecd..183f7514d2d 100644 --- a/src/backend/utils/activity/Makefile +++ b/src/backend/utils/activity/Makefile @@ -27,6 +27,7 @@ OBJS = \ pgstat_function.o \ pgstat_io.o \ pgstat_relation.o \ + pgstat_vacuum.o \ pgstat_replslot.o \ pgstat_shmem.o \ pgstat_slru.o \ diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 09fa0fbee57..8a5f355e9bc 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -478,6 +478,34 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE] .reset_all_cb = pgstat_wal_reset_all_cb, .snapshot_cb = pgstat_wal_snapshot_cb, }, + [PGSTAT_KIND_VACUUM_DB] = { + .name = "vacuum statistics", + + .fixed_amount = false, + .write_to_file = true, + /* so pg_stat_database entries can be seen in all databases */ + .accessed_across_databases = true, + + .shared_size = sizeof(PgStatShared_VacuumDB), + .shared_data_off = offsetof(PgStatShared_VacuumDB, stats), + .shared_data_len = sizeof(((PgStatShared_VacuumDB *) 0)->stats), + .pending_size = sizeof(PgStat_VacuumDBCounts), + + .flush_pending_cb = pgstat_vacuum_db_flush_cb, + }, + [PGSTAT_KIND_VACUUM_RELATION] = { + .name = "vacuum statistics", + + .fixed_amount = false, + .write_to_file = true, + + .shared_size = sizeof(PgStatShared_VacuumRelation), + .shared_data_off = offsetof(PgStatShared_VacuumRelation, stats), + .shared_data_len = sizeof(((PgStatShared_VacuumRelation *) 0)->stats), + .pending_size = sizeof(PgStat_RelationVacuumPending), + + .flush_pending_cb = pgstat_vacuum_relation_flush_cb + }, }; /* diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c index d5c1e2a2cf5..344f0a24683 100644 --- a/src/backend/utils/activity/pgstat_database.c +++ b/src/backend/utils/activity/pgstat_database.c @@ -46,6 +46,15 @@ pgstat_drop_database(Oid databaseid) pgstat_drop_transactional(PGSTAT_KIND_DATABASE, databaseid, InvalidOid); } +/* + * Remove entry for the database being dropped. + */ +void +pgstat_drop_vacuum_database(Oid databaseid) +{ + pgstat_drop_transactional(PGSTAT_KIND_VACUUM_DB, databaseid, InvalidOid); +} + /* * Called from autovacuum.c to report startup of an autovacuum process. * We are called before InitPostgres is done, so can't rely on MyDatabaseId; @@ -449,7 +458,6 @@ pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) pgstat_unlock_entry(entry_ref); memset(pendingent, 0, sizeof(*pendingent)); - memset(&(pendingent)->vacuum_ext, 0, sizeof(ExtVacReport)); return true; } diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 5d36d5a2140..db6dba70331 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -47,8 +47,6 @@ static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_lev static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info); static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop); static void restore_truncdrop_counters(PgStat_TableXactStatus *trans); -static void pgstat_accumulate_extvac_stats(ExtVacReport *dst, ExtVacReport *src, - bool accumulate_reltype_specific_info); /* @@ -205,50 +203,17 @@ pgstat_drop_relation(Relation rel) } } -/* --------- - * pgstat_report_vacuum_error() - - * - * Tell the collector about an (auto)vacuum interruption. - * --------- - */ -void -pgstat_report_vacuum_error(Oid tableoid, ExtVacReportType m_type) -{ - PgStat_EntryRef *entry_ref; - PgStatShared_Relation *shtabentry; - PgStat_StatTabEntry *tabentry; - Oid dboid = MyDatabaseId; - PgStat_StatDBEntry *dbentry; /* pending database entry */ - - if (!pgstat_track_counts) - return; - - entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, - dboid, tableoid, false); - - shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats; - tabentry = &shtabentry->stats; - - tabentry->vacuum_ext.type = m_type; - pgstat_unlock_entry(entry_ref); - - dbentry = pgstat_prep_database_pending(dboid); - dbentry->vacuum_ext.errors++; - dbentry->vacuum_ext.type = m_type; -} - /* * Report that the table was just vacuumed and flush IO statistics. */ void pgstat_report_vacuum(Oid tableoid, bool shared, PgStat_Counter livetuples, PgStat_Counter deadtuples, - TimestampTz starttime, ExtVacReport *params) + TimestampTz starttime) { PgStat_EntryRef *entry_ref; PgStatShared_Relation *shtabentry; PgStat_StatTabEntry *tabentry; - PgStatShared_Database *dbentry; Oid dboid = (shared ? InvalidOid : MyDatabaseId); TimestampTz ts; PgStat_Counter elapsedtime; @@ -270,8 +235,6 @@ pgstat_report_vacuum(Oid tableoid, bool shared, tabentry->live_tuples = livetuples; tabentry->dead_tuples = deadtuples; - pgstat_accumulate_extvac_stats(&tabentry->vacuum_ext, params, true); - /* * It is quite possible that a non-aggressive VACUUM ended up skipping * various pages, however, we'll zero the insert counter here regardless. @@ -307,16 +270,6 @@ pgstat_report_vacuum(Oid tableoid, bool shared, */ pgstat_flush_io(false); (void) pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO); - - if (dboid != InvalidOid) - { - entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, - dboid, InvalidOid, false); - dbentry = (PgStatShared_Database *) entry_ref->shared_stats; - - pgstat_accumulate_extvac_stats(&dbentry->stats.vacuum_ext, params, false); - pgstat_unlock_entry(entry_ref); - } } /* @@ -942,6 +895,12 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) return true; } +void +pgstat_vacuum_relation_delete_pending_cb(Oid relid) +{ + pgstat_drop_transactional(PGSTAT_KIND_VACUUM_RELATION, relid, InvalidOid); +} + void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref) { @@ -1044,60 +1003,4 @@ restore_truncdrop_counters(PgStat_TableXactStatus *trans) trans->tuples_updated = trans->updated_pre_truncdrop; trans->tuples_deleted = trans->deleted_pre_truncdrop; } -} - -static void -pgstat_accumulate_extvac_stats(ExtVacReport *dst, ExtVacReport *src, - bool accumulate_reltype_specific_info) -{ - if(!pgstat_track_vacuum_statistics) - return; - - dst->total_blks_read += src->total_blks_read; - dst->total_blks_hit += src->total_blks_hit; - dst->total_blks_dirtied += src->total_blks_dirtied; - dst->total_blks_written += src->total_blks_written; - dst->wal_bytes += src->wal_bytes; - dst->wal_fpi += src->wal_fpi; - dst->wal_records += src->wal_records; - dst->blk_read_time += src->blk_read_time; - dst->blk_write_time += src->blk_write_time; - dst->delay_time += src->delay_time; - dst->total_time += src->total_time; - dst->wraparound_failsafe_count += src->wraparound_failsafe_count; - dst->errors += src->errors; - - if (!accumulate_reltype_specific_info) - return; - - if (dst->type == PGSTAT_EXTVAC_INVALID) - dst->type = src->type; - - Assert(src->type == PGSTAT_EXTVAC_INVALID || src->type == dst->type); - - if (dst->type == src->type) - { - dst->blks_fetched += src->blks_fetched; - dst->blks_hit += src->blks_hit; - - if (dst->type == PGSTAT_EXTVAC_TABLE) - { - dst->table.pages_scanned += src->table.pages_scanned; - dst->table.pages_removed += src->table.pages_removed; - dst->table.vm_new_frozen_pages += src->table.vm_new_frozen_pages; - dst->table.vm_new_visible_pages += src->table.vm_new_visible_pages; - dst->table.vm_new_visible_frozen_pages += src->table.vm_new_visible_frozen_pages; - dst->tuples_deleted += src->tuples_deleted; - dst->table.tuples_frozen += src->table.tuples_frozen; - dst->table.recently_dead_tuples += src->table.recently_dead_tuples; - dst->table.index_vacuum_count += src->table.index_vacuum_count; - dst->table.missed_dead_pages += src->table.missed_dead_pages; - dst->table.missed_dead_tuples += src->table.missed_dead_tuples; - } - else if (dst->type == PGSTAT_EXTVAC_INDEX) - { - dst->index.pages_deleted += src->index.pages_deleted; - dst->tuples_deleted += src->tuples_deleted; - } - } } \ No newline at end of file diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index c2acdcf0e0e..3605ec98317 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -2275,14 +2275,14 @@ pg_stat_get_vacuum_tables(PG_FUNCTION_ARGS) #define PG_STAT_GET_VACUUM_TABLES_STATS_COLS 26 Oid relid = PG_GETARG_OID(0); - PgStat_StatTabEntry *tabentry; - ExtVacReport *extvacuum; + PgStat_VacuumRelationCounts *extvacuum; + PgStat_RelationVacuumPending *pending; TupleDesc tupdesc; Datum values[PG_STAT_GET_VACUUM_TABLES_STATS_COLS] = {0}; bool nulls[PG_STAT_GET_VACUUM_TABLES_STATS_COLS] = {0}; char buf[256]; int i = 0; - ExtVacReport allzero; + PgStat_VacuumRelationCounts allzero; /* Initialise attributes information in the tuple descriptor */ tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_VACUUM_TABLES_STATS_COLS); @@ -2346,18 +2346,16 @@ pg_stat_get_vacuum_tables(PG_FUNCTION_ARGS) BlessTupleDesc(tupdesc); - tabentry = pgstat_fetch_stat_tabentry(relid); + pending = find_vacuum_relation_entry(relid); - if (tabentry == NULL) + if (pending == NULL) { /* If the subscription is not found, initialise its stats */ - memset(&allzero, 0, sizeof(ExtVacReport)); + memset(&allzero, 0, sizeof(PgStat_VacuumRelationCounts)); extvacuum = &allzero; } else - { - extvacuum = &(tabentry->vacuum_ext); - } + extvacuum = &(pending->counts); i = 0; @@ -2416,14 +2414,14 @@ pg_stat_get_vacuum_indexes(PG_FUNCTION_ARGS) #define PG_STAT_GET_VACUUM_INDEX_STATS_COLS 16 Oid relid = PG_GETARG_OID(0); - PgStat_StatTabEntry *tabentry; - ExtVacReport *extvacuum; + PgStat_VacuumRelationCounts *extvacuum; + PgStat_RelationVacuumPending *pending; TupleDesc tupdesc; Datum values[PG_STAT_GET_VACUUM_INDEX_STATS_COLS] = {0}; bool nulls[PG_STAT_GET_VACUUM_INDEX_STATS_COLS] = {0}; char buf[256]; int i = 0; - ExtVacReport allzero; + PgStat_VacuumRelationCounts allzero; /* Initialise attributes information in the tuple descriptor */ tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_VACUUM_INDEX_STATS_COLS); @@ -2467,18 +2465,16 @@ pg_stat_get_vacuum_indexes(PG_FUNCTION_ARGS) BlessTupleDesc(tupdesc); - tabentry = pgstat_fetch_stat_tabentry(relid); + pending = find_vacuum_relation_entry(relid); - if (tabentry == NULL) + if (pending == NULL) { /* If the subscription is not found, initialise its stats */ - memset(&allzero, 0, sizeof(ExtVacReport)); + memset(&allzero, 0, sizeof(PgStat_VacuumRelationCounts)); extvacuum = &allzero; } - else - { - extvacuum = &(tabentry->vacuum_ext); - } + + extvacuum = &(pending->counts); i = 0; @@ -2523,14 +2519,14 @@ pg_stat_get_vacuum_database(PG_FUNCTION_ARGS) #define PG_STAT_GET_VACUUM_DATABASE_STATS_COLS 14 Oid dbid = PG_GETARG_OID(0); - PgStat_StatDBEntry *dbentry; - ExtVacReport *extvacuum; + PgStat_VacuumDBCounts *extvacuum; TupleDesc tupdesc; Datum values[PG_STAT_GET_VACUUM_DATABASE_STATS_COLS] = {0}; bool nulls[PG_STAT_GET_VACUUM_DATABASE_STATS_COLS] = {0}; char buf[256]; int i = 0; - ExtVacReport allzero; + + PG_RETURN_NULL(); /* Initialise attributes information in the tuple descriptor */ tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_VACUUM_DATABASE_STATS_COLS); @@ -2570,18 +2566,7 @@ pg_stat_get_vacuum_database(PG_FUNCTION_ARGS) BlessTupleDesc(tupdesc); - dbentry = pgstat_fetch_stat_dbentry(dbid); - - if (dbentry == NULL) - { - /* If the subscription is not found, initialise its stats */ - memset(&allzero, 0, sizeof(ExtVacReport)); - extvacuum = &allzero; - } - else - { - extvacuum = &(dbentry->vacuum_ext); - } + extvacuum = pgstat_prep_vacuum_database_pending(dbid); i = 0; diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index fb134f3402e..f895151ca09 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -432,5 +432,5 @@ extern double anl_get_next_S(double t, int n, double *stateptr); extern void extvac_stats_start_idx(Relation rel, IndexBulkDeleteResult *stats, LVExtStatCountersIdx *counters); extern void extvac_stats_end_idx(Relation rel, IndexBulkDeleteResult *stats, - LVExtStatCountersIdx *counters, ExtVacReport *report); + LVExtStatCountersIdx *counters, PgStat_VacuumRelationCounts *report); #endif /* VACUUM_H */ diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 66e6e721563..1760b35b5eb 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -119,9 +119,56 @@ typedef enum ExtVacReportType PGSTAT_EXTVAC_INDEX = 2 } ExtVacReportType; +/* ---------- + * PgStat_TableCounts The actual per-table counts kept by a backend + * + * This struct should contain only actual event counters, because we make use + * of pg_memory_is_all_zeros() to detect whether there are any stats updates + * to apply. + * + * It is a component of PgStat_TableStatus (within-backend state). + * + * Note: for a table, tuples_returned is the number of tuples successfully + * fetched by heap_getnext, while tuples_fetched is the number of tuples + * successfully fetched by heap_fetch under the control of bitmap indexscans. + * For an index, tuples_returned is the number of index entries returned by + * the index AM, while tuples_fetched is the number of tuples successfully + * fetched by heap_fetch under the control of simple indexscans for this index. + * + * tuples_inserted/updated/deleted/hot_updated/newpage_updated count attempted + * actions, regardless of whether the transaction committed. delta_live_tuples, + * delta_dead_tuples, and changed_tuples are set depending on commit or abort. + * Note that delta_live_tuples and delta_dead_tuples can be negative! + * ---------- + */ +typedef struct PgStat_TableCounts +{ + PgStat_Counter numscans; + + PgStat_Counter tuples_returned; + PgStat_Counter tuples_fetched; + + PgStat_Counter tuples_inserted; + PgStat_Counter tuples_updated; + PgStat_Counter tuples_deleted; + PgStat_Counter tuples_hot_updated; + PgStat_Counter tuples_newpage_updated; + bool truncdropped; + + PgStat_Counter delta_live_tuples; + PgStat_Counter delta_dead_tuples; + PgStat_Counter changed_tuples; + + PgStat_Counter blocks_fetched; + PgStat_Counter blocks_hit; + + PgStat_Counter rev_all_visible_pages; + PgStat_Counter rev_all_frozen_pages; +} PgStat_TableCounts; + /* ---------- * - * ExtVacReport + * PgStat_VacuumRelationCounts * * Additional statistics of vacuum processing over a relation. * pages_removed is the amount by which the physically shrank, @@ -129,7 +176,7 @@ typedef enum ExtVacReportType * pages_deleted refer to free space within the index file * ---------- */ -typedef struct ExtVacReport +typedef struct PgStat_VacuumRelationCounts { /* number of blocks missed, hit, dirtied and written during a vacuum of specific relation */ int64 total_blks_read; @@ -154,7 +201,6 @@ typedef struct ExtVacReport int64 tuples_deleted; /* tuples deleted by vacuum */ - int32 errors; int32 wraparound_failsafe_count; /* the number of times to prevent wraparound problem */ ExtVacReportType type; /* heap, index, etc. */ @@ -192,61 +238,44 @@ typedef struct ExtVacReport int64 pages_deleted; /* number of pages deleted by vacuum */ } index; } /* per_type_stats */; -} ExtVacReport; +} PgStat_VacuumRelationCounts; -/* ---------- - * PgStat_TableCounts The actual per-table counts kept by a backend - * - * This struct should contain only actual event counters, because we make use - * of pg_memory_is_all_zeros() to detect whether there are any stats updates - * to apply. - * - * It is a component of PgStat_TableStatus (within-backend state). - * - * Note: for a table, tuples_returned is the number of tuples successfully - * fetched by heap_getnext, while tuples_fetched is the number of tuples - * successfully fetched by heap_fetch under the control of bitmap indexscans. - * For an index, tuples_returned is the number of index entries returned by - * the index AM, while tuples_fetched is the number of tuples successfully - * fetched by heap_fetch under the control of simple indexscans for this index. - * - * tuples_inserted/updated/deleted/hot_updated/newpage_updated count attempted - * actions, regardless of whether the transaction committed. delta_live_tuples, - * delta_dead_tuples, and changed_tuples are set depending on commit or abort. - * Note that delta_live_tuples and delta_dead_tuples can be negative! - * ---------- - */ -typedef struct PgStat_TableCounts +typedef struct PgStat_VacuumRelationStatus { - PgStat_Counter numscans; + Oid id; /* table's OID */ + bool shared; /* is it a shared catalog? */ + PgStat_VacuumRelationCounts counts; /* event counts to be sent */ +} PgStat_VacuumRelationStatus; - PgStat_Counter tuples_returned; - PgStat_Counter tuples_fetched; +typedef struct PgStat_VacuumDBCounts +{ + Oid dbjid; + /* number of blocks missed, hit, dirtied and written during a vacuum of specific relation */ + int64 total_blks_read; + int64 total_blks_hit; + int64 total_blks_dirtied; + int64 total_blks_written; - PgStat_Counter tuples_inserted; - PgStat_Counter tuples_updated; - PgStat_Counter tuples_deleted; - PgStat_Counter tuples_hot_updated; - PgStat_Counter tuples_newpage_updated; - bool truncdropped; + /* blocks missed and hit for just the heap during a vacuum of specific relation */ + int64 blks_fetched; + int64 blks_hit; - PgStat_Counter delta_live_tuples; - PgStat_Counter delta_dead_tuples; - PgStat_Counter changed_tuples; + /* Vacuum WAL usage stats */ + int64 wal_records; /* wal usage: number of WAL records */ + int64 wal_fpi; /* wal usage: number of WAL full page images produced */ + uint64 wal_bytes; /* wal usage: size of WAL records produced */ - PgStat_Counter blocks_fetched; - PgStat_Counter blocks_hit; + /* Time stats. */ + double blk_read_time; /* time spent reading pages, in msec */ + double blk_write_time; /* time spent writing pages, in msec */ + double delay_time; /* how long vacuum slept in vacuum delay point, in msec */ + double total_time; /* total time of a vacuum operation, in msec */ - PgStat_Counter rev_all_visible_pages; - PgStat_Counter rev_all_frozen_pages; + int64 tuples_deleted; /* tuples deleted by vacuum */ - /* - * Additional cumulative stat on vacuum operations. - * Use an expensive structure as an abstraction for different types of - * relations. - */ - ExtVacReport vacuum_ext; -} PgStat_TableCounts; + int32 errors; + int32 wraparound_failsafe_count; /* the number of times to prevent wraparound problem */ +} PgStat_VacuumDBCounts; /* ---------- * PgStat_TableStatus Per-table status within a backend @@ -272,6 +301,12 @@ typedef struct PgStat_TableStatus Relation relation; /* rel that is using this entry */ } PgStat_TableStatus; +typedef struct PgStat_RelationVacuumPending +{ + Oid id; /* table's OID */ + PgStat_VacuumRelationCounts counts; /* event counts to be sent */ +} PgStat_RelationVacuumPending; + /* ---------- * PgStat_TableXactStatus Per-table, per-subtransaction status * ---------- @@ -468,8 +503,6 @@ typedef struct PgStat_StatDBEntry PgStat_Counter parallel_workers_launched; TimestampTz stat_reset_timestamp; - - ExtVacReport vacuum_ext; /* extended vacuum statistics */ } PgStat_StatDBEntry; typedef struct PgStat_StatFuncEntry @@ -551,8 +584,6 @@ typedef struct PgStat_StatTabEntry PgStat_Counter rev_all_visible_pages; PgStat_Counter rev_all_frozen_pages; - - ExtVacReport vacuum_ext; } PgStat_StatTabEntry; /* ------ @@ -760,7 +791,7 @@ extern void pgstat_unlink_relation(Relation rel); extern void pgstat_report_vacuum(Oid tableoid, bool shared, PgStat_Counter livetuples, PgStat_Counter deadtuples, - TimestampTz starttime, ExtVacReport *params); + TimestampTz starttime); extern void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, bool resetcounter, TimestampTz starttime); @@ -895,6 +926,15 @@ extern int pgstat_get_transactional_drops(bool isCommit, struct xl_xact_stats_it extern void pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items, bool is_redo); +extern void pgstat_drop_vacuum_database(Oid databaseid); +extern void pgstat_vacuum_relation_delete_pending_cb(Oid relid); +extern void +pgstat_report_tab_vacuum_extstats(Oid tableoid, bool shared, + PgStat_VacuumRelationCounts *params); +extern PgStat_RelationVacuumPending * find_vacuum_relation_entry(Oid relid); +extern PgStat_VacuumDBCounts *pgstat_prep_vacuum_database_pending(Oid dboid); +extern PgStat_VacuumRelationCounts *pgstat_fetch_stat_vacuum_tabentry(Oid relid); + /* * Functions in pgstat_wal.c */ diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index d5557e6e998..140adbcdbd6 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -439,6 +439,18 @@ typedef struct PgStatShared_Relation PgStat_StatTabEntry stats; } PgStatShared_Relation; +typedef struct PgStatShared_VacuumDB +{ + PgStatShared_Common header; + PgStat_VacuumDBCounts stats; +} PgStatShared_VacuumDB; + +typedef struct PgStatShared_VacuumRelation +{ + PgStatShared_Common header; + PgStat_VacuumRelationCounts stats; +} PgStatShared_VacuumRelation; + typedef struct PgStatShared_Function { PgStatShared_Common header; @@ -607,6 +619,9 @@ extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid); extern void pgstat_snapshot_fixed(PgStat_Kind kind); +bool pgstat_vacuum_db_flush_cb(PgStat_EntryRef *entry_ref, bool nowait); +extern bool pgstat_vacuum_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait); + /* * Functions in pgstat_archiver.c diff --git a/src/include/utils/pgstat_kind.h b/src/include/utils/pgstat_kind.h index f44169fd5a3..454661f9d6a 100644 --- a/src/include/utils/pgstat_kind.h +++ b/src/include/utils/pgstat_kind.h @@ -38,9 +38,11 @@ #define PGSTAT_KIND_IO 10 #define PGSTAT_KIND_SLRU 11 #define PGSTAT_KIND_WAL 12 +#define PGSTAT_KIND_VACUUM_DB 13 +#define PGSTAT_KIND_VACUUM_RELATION 14 #define PGSTAT_KIND_BUILTIN_MIN PGSTAT_KIND_DATABASE -#define PGSTAT_KIND_BUILTIN_MAX PGSTAT_KIND_WAL +#define PGSTAT_KIND_BUILTIN_MAX PGSTAT_KIND_VACUUM_RELATION #define PGSTAT_KIND_BUILTIN_SIZE (PGSTAT_KIND_BUILTIN_MAX + 1) /* Custom stats kinds */