diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/system_views.sql | 18 | ||||
-rw-r--r-- | src/backend/commands/vacuumlazy.c | 78 | ||||
-rw-r--r-- | src/backend/postmaster/pgstat.c | 29 |
3 files changed, 125 insertions, 0 deletions
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 84aa06148ef..fef67bdd4cd 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -796,6 +796,24 @@ CREATE VIEW pg_stat_bgwriter AS pg_stat_get_buf_alloc() AS buffers_alloc, pg_stat_get_bgwriter_stat_reset_time() AS stats_reset; +CREATE VIEW pg_stat_progress_vacuum AS + SELECT + S.pid AS pid, S.datid AS datid, D.datname AS datname, + S.relid AS relid, + CASE S.param1 WHEN 0 THEN 'initializing' + WHEN 1 THEN 'scanning heap' + WHEN 2 THEN 'vacuuming indexes' + WHEN 3 THEN 'vacuuming heap' + WHEN 4 THEN 'cleaning up indexes' + WHEN 5 THEN 'truncating heap' + WHEN 6 THEN 'performing final cleanup' + END AS phase, + S.param2 AS heap_blks_total, S.param3 AS heap_blks_scanned, + S.param4 AS heap_blks_vacuumed, S.param5 AS index_vacuum_count, + S.param6 AS max_dead_tuples, S.param7 AS num_dead_tuples + FROM pg_stat_get_progress_info('VACUUM') AS S + JOIN pg_database D ON S.datid = D.oid; + CREATE VIEW pg_user_mappings AS SELECT U.oid AS umid, diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index fe87243f4c5..163c121560d 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -48,6 +48,7 @@ #include "catalog/catalog.h" #include "catalog/storage.h" #include "commands/dbcommands.h" +#include "commands/progress.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "pgstat.h" @@ -272,6 +273,10 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, if (should_attempt_truncation(vacrelstats)) lazy_truncate_heap(onerel, vacrelstats); + /* Report that we are now doing final cleanup */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_FINAL_CLEANUP); + /* Vacuum the Free Space Map */ FreeSpaceMapVacuum(onerel); @@ -457,6 +462,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, bool skipping_blocks; xl_heap_freeze_tuple *frozen; StringInfoData buf; + const int initprog_index[] = { + PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_TOTAL_HEAP_BLKS, + PROGRESS_VACUUM_MAX_DEAD_TUPLES + }; + int64 initprog_val[3]; pg_rusage_init(&ru0); @@ -481,6 +492,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, lazy_space_alloc(vacrelstats, nblocks); frozen = palloc(sizeof(xl_heap_freeze_tuple) * MaxHeapTuplesPerPage); + /* Report that we're scanning the heap, advertising total # of blocks */ + initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; + initprog_val[1] = nblocks; + initprog_val[2] = vacrelstats->max_dead_tuples; + pgstat_progress_update_multi_param(3, initprog_index, initprog_val); + /* * Except when aggressive is set, we want to skip pages that are * all-visible according to the visibility map, but only when we can skip @@ -572,6 +589,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, #define FORCE_CHECK_PAGE() \ (blkno == nblocks - 1 && should_attempt_truncation(vacrelstats)) + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + if (blkno == next_unskippable_block) { /* Time to advance next_unskippable_block */ @@ -652,6 +671,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, if ((vacrelstats->max_dead_tuples - vacrelstats->num_dead_tuples) < MaxHeapTuplesPerPage && vacrelstats->num_dead_tuples > 0) { + const int hvp_index[] = { + PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_NUM_INDEX_VACUUMS + }; + int64 hvp_val[2]; + /* * Before beginning index vacuuming, we release any pin we may * hold on the visibility map page. This isn't necessary for @@ -667,11 +692,26 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* Log cleanup info before we touch indexes */ vacuum_log_cleanup_info(onerel, vacrelstats); + /* Report that we are now vacuuming indexes */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_VACUUM_INDEX); + /* Remove index entries */ for (i = 0; i < nindexes; i++) lazy_vacuum_index(Irel[i], &indstats[i], vacrelstats); + + /* + * Report that we are now vacuuming the heap. We also increase + * the number of index scans here; note that by using + * pgstat_progress_update_multi_param we can update both + * parameters atomically. + */ + hvp_val[0] = PROGRESS_VACUUM_PHASE_VACUUM_HEAP; + hvp_val[1] = vacrelstats->num_index_scans + 1; + pgstat_progress_update_multi_param(2, hvp_index, hvp_val); + /* Remove tuples from heap */ lazy_vacuum_heap(onerel, vacrelstats); @@ -682,6 +722,10 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, */ vacrelstats->num_dead_tuples = 0; vacrelstats->num_index_scans++; + + /* Report that we are once again scanning the heap */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_SCAN_HEAP); } /* @@ -1182,6 +1226,10 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, RecordPageWithFreeSpace(onerel, blkno, freespace); } + /* report that everything is scanned and vacuumed */ + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pfree(frozen); /* save stats for use later */ @@ -1208,19 +1256,41 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* XXX put a threshold on min number of tuples here? */ if (vacrelstats->num_dead_tuples > 0) { + const int hvp_index[] = { + PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_NUM_INDEX_VACUUMS + }; + int64 hvp_val[2]; + /* Log cleanup info before we touch indexes */ vacuum_log_cleanup_info(onerel, vacrelstats); + /* Report that we are now vacuuming indexes */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_VACUUM_INDEX); + /* Remove index entries */ for (i = 0; i < nindexes; i++) lazy_vacuum_index(Irel[i], &indstats[i], vacrelstats); + + /* Report that we are now vacuuming the heap */ + hvp_val[0] = PROGRESS_VACUUM_PHASE_VACUUM_HEAP; + hvp_val[1] = vacrelstats->num_index_scans + 1; + pgstat_progress_update_multi_param(2, hvp_index, hvp_val); + /* Remove tuples from heap */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_VACUUM_HEAP); lazy_vacuum_heap(onerel, vacrelstats); vacrelstats->num_index_scans++; } + /* report we're now in the cleanup phase */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_INDEX_CLEANUP); + /* Do post-vacuum cleanup and statistics update for each index */ for (i = 0; i < nindexes; i++) lazy_cleanup_index(Irel[i], indstats[i], vacrelstats); @@ -1350,6 +1420,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, TransactionId visibility_cutoff_xid; bool all_frozen; + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + START_CRIT_SECTION(); for (; tupindex < vacrelstats->num_dead_tuples; tupindex++) @@ -1607,6 +1679,10 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats) pg_rusage_init(&ru0); + /* Report that we are now truncating */ + pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, + PROGRESS_VACUUM_PHASE_TRUNCATE); + /* * Loop until no more truncating can be done. */ @@ -1887,6 +1963,8 @@ lazy_record_dead_tuple(LVRelStats *vacrelstats, { vacrelstats->dead_tuples[vacrelstats->num_dead_tuples] = *itemptr; vacrelstats->num_dead_tuples++; + pgstat_progress_update_param(PROGRESS_VACUUM_NUM_DEAD_TUPLES, + vacrelstats->num_dead_tuples); } } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 14afef61fef..bfe70fc41db 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2903,6 +2903,35 @@ pgstat_progress_update_param(int index, int64 val) } /*----------- + * pgstat_progress_update_params() - + * + * Automatically update multiple members in st_progress_param[] of own backend + * entry. + *----------- + */ +void +pgstat_progress_update_multi_param(int nparam, const int *index, + const int64 *val) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + int i; + + if (!beentry || !pgstat_track_activities || nparam == 0) + return; + + pgstat_increment_changecount_before(beentry); + + for (i = 0; i < nparam; ++i) + { + Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM); + + beentry->st_progress_param[index[i]] = val[i]; + } + + pgstat_increment_changecount_after(beentry); +} + +/*----------- * pgstat_progress_end_command() - * * Reset st_progress_command (and st_progress_command_target) in own backend |