mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Report per-index vacuum progress in pg_stat_progress_vacuum
pg_stat_progress_vacuum gains three fields, reflecting some activity related to index cleanups during VACUUM, which is a phase that could take a long time depending on the quantity of data to treat and the number of indexes: - current_index_relid, the index being processed. - index_blks_total, total number of blocks to process. - index_blks_done, number of blocks already processed. There fields are new, and do not reuse the existing fields related to heap as index cleanups may need multiple passes, where knowing both the heap activity and the index activity could be relevant. This is unlikely since tids are accumulated in the heap scanning phase using an optimized radix tree, still possible. VACUUM can spawn parallel workers to clean indexes (each worker cleans a different index); these should up in the progress view in the shape of one extra row for each worker. Bump catalog version. Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> Reviewed-by: Sami Imseih <samimseih@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Shihao Zhong <zhong950419@gmail.com> Discussion: https://postgr.es/m/CALj2ACUgwSchK6jQ2CdKLBWUADTOE_zKdTff2Zg3E6hOuXKv-w@mail.gmail.com
This commit is contained in:
@@ -7685,8 +7685,10 @@ FROM pg_stat_get_backend_idset() AS backendid;
|
||||
<para>
|
||||
Whenever <command>VACUUM</command> is running, the
|
||||
<structname>pg_stat_progress_vacuum</structname> view will contain
|
||||
one row for each backend (including autovacuum worker processes) that is
|
||||
currently vacuuming. The tables below describe the information
|
||||
one row for each backend (including autovacuum worker processes and
|
||||
parallel workers launched for
|
||||
<link linkend="sql-vacuum">parallel vacuum</link>) that is currently
|
||||
vacuuming. The tables below describe the information
|
||||
that will be reported and provide information about how to interpret it.
|
||||
Progress for <command>VACUUM FULL</command> commands is reported via
|
||||
<structname>pg_stat_progress_repack</structname>, and is also visible via
|
||||
@@ -7944,10 +7946,61 @@ FROM pg_stat_get_backend_idset() AS backendid;
|
||||
</itemizedlist>
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="catalog_table_entry"><para role="column_definition">
|
||||
<structfield>current_index_relid</structfield> <type>oid</type>
|
||||
</para>
|
||||
<para>
|
||||
OID of the index currently being vacuumed, or 0 if none is. This
|
||||
field is only valid when the phase is
|
||||
<literal>vacuuming indexes</literal> or
|
||||
<literal>cleaning up indexes</literal>.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="catalog_table_entry"><para role="column_definition">
|
||||
<structfield>index_blks_total</structfield> <type>bigint</type>
|
||||
</para>
|
||||
<para>
|
||||
Total number of blocks in the index identified by
|
||||
<structfield>current_index_relid</structfield>. Only B-tree indexes
|
||||
report this; it is 0 for other index access methods, and when no index
|
||||
scan is in progress.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="catalog_table_entry"><para role="column_definition">
|
||||
<structfield>index_blks_done</structfield> <type>bigint</type>
|
||||
</para>
|
||||
<para>
|
||||
Number of blocks of that index scanned so far. It stops one block
|
||||
short of <structfield>index_blks_total</structfield>, which counts the
|
||||
index metapage, never scanned.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
During a parallel vacuum, the leader and each of its workers reports its
|
||||
own row, all sharing the same <structfield>relid</structfield>.
|
||||
Only <structfield>phase</structfield>,
|
||||
<structfield>current_index_relid</structfield>,
|
||||
<structfield>index_blks_total</structfield> and
|
||||
<structfield>index_blks_done</structfield> are maintained on a worker row;
|
||||
the remaining columns track command-level progress that only the leader
|
||||
maintains. Use <structfield>leader_pid</structfield> in
|
||||
<link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
|
||||
to tell the leader row from its worker rows.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<table id="vacuum-phases">
|
||||
<title>VACUUM Phases</title>
|
||||
<tgroup cols="2">
|
||||
|
||||
@@ -3038,17 +3038,27 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
|
||||
{
|
||||
IndexVacuumInfo ivinfo;
|
||||
LVSavedErrInfo saved_err_info;
|
||||
const int reset_index[] = {
|
||||
PROGRESS_VACUUM_CURRENT_INDEX_RELID,
|
||||
PROGRESS_SCAN_BLOCKS_TOTAL,
|
||||
PROGRESS_SCAN_BLOCKS_DONE
|
||||
};
|
||||
const int64 reset_val[] = {(int64) InvalidOid, 0, 0};
|
||||
|
||||
ivinfo.index = indrel;
|
||||
ivinfo.heaprel = vacrel->rel;
|
||||
ivinfo.analyze_only = false;
|
||||
ivinfo.is_autovacuum = AmAutoVacuumWorkerProcess();
|
||||
ivinfo.report_progress = false;
|
||||
ivinfo.report_progress = true;
|
||||
ivinfo.estimated_count = true;
|
||||
ivinfo.message_level = DEBUG2;
|
||||
ivinfo.num_heap_tuples = reltuples;
|
||||
ivinfo.strategy = vacrel->bstrategy;
|
||||
|
||||
/* Report which index we're currently processing */
|
||||
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
|
||||
(int64) RelationGetRelid(indrel));
|
||||
|
||||
/*
|
||||
* Update error traceback information.
|
||||
*
|
||||
@@ -3070,6 +3080,8 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
|
||||
pfree(vacrel->indname);
|
||||
vacrel->indname = NULL;
|
||||
|
||||
pgstat_progress_update_multi_param(3, reset_index, reset_val);
|
||||
|
||||
return istat;
|
||||
}
|
||||
|
||||
@@ -3089,18 +3101,28 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
|
||||
{
|
||||
IndexVacuumInfo ivinfo;
|
||||
LVSavedErrInfo saved_err_info;
|
||||
const int reset_index[] = {
|
||||
PROGRESS_VACUUM_CURRENT_INDEX_RELID,
|
||||
PROGRESS_SCAN_BLOCKS_TOTAL,
|
||||
PROGRESS_SCAN_BLOCKS_DONE
|
||||
};
|
||||
const int64 reset_val[] = {(int64) InvalidOid, 0, 0};
|
||||
|
||||
ivinfo.index = indrel;
|
||||
ivinfo.heaprel = vacrel->rel;
|
||||
ivinfo.analyze_only = false;
|
||||
ivinfo.is_autovacuum = AmAutoVacuumWorkerProcess();
|
||||
ivinfo.report_progress = false;
|
||||
ivinfo.report_progress = true;
|
||||
ivinfo.estimated_count = estimated_count;
|
||||
ivinfo.message_level = DEBUG2;
|
||||
|
||||
ivinfo.num_heap_tuples = reltuples;
|
||||
ivinfo.strategy = vacrel->bstrategy;
|
||||
|
||||
/* Report which index we're currently processing */
|
||||
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
|
||||
(int64) RelationGetRelid(indrel));
|
||||
|
||||
/*
|
||||
* Update error traceback information.
|
||||
*
|
||||
@@ -3120,6 +3142,8 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
|
||||
pfree(vacrel->indname);
|
||||
vacrel->indname = NULL;
|
||||
|
||||
pgstat_progress_update_multi_param(3, reset_index, reset_val);
|
||||
|
||||
return istat;
|
||||
}
|
||||
|
||||
|
||||
@@ -1353,7 +1353,10 @@ CREATE VIEW pg_stat_progress_vacuum AS
|
||||
CASE S.param13 WHEN 1 THEN 'manual'
|
||||
WHEN 2 THEN 'autovacuum'
|
||||
WHEN 3 THEN 'autovacuum_wraparound'
|
||||
ELSE NULL END AS started_by
|
||||
ELSE NULL END AS started_by,
|
||||
CAST(S.param14 AS oid) AS current_index_relid,
|
||||
S.param16 AS index_blks_total,
|
||||
S.param17 AS index_blks_done
|
||||
FROM pg_stat_get_progress_info('VACUUM') AS S
|
||||
LEFT JOIN pg_database D ON S.datid = D.oid;
|
||||
|
||||
|
||||
@@ -1115,6 +1115,17 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
|
||||
IndexBulkDeleteResult *istat = NULL;
|
||||
IndexBulkDeleteResult *istat_res;
|
||||
IndexVacuumInfo ivinfo;
|
||||
const int progress_index[] = {
|
||||
PROGRESS_VACUUM_PHASE,
|
||||
PROGRESS_VACUUM_CURRENT_INDEX_RELID
|
||||
};
|
||||
int64 progress_val[2];
|
||||
const int reset_index[] = {
|
||||
PROGRESS_VACUUM_CURRENT_INDEX_RELID,
|
||||
PROGRESS_SCAN_BLOCKS_TOTAL,
|
||||
PROGRESS_SCAN_BLOCKS_DONE
|
||||
};
|
||||
const int64 reset_val[] = {(int64) InvalidOid, 0, 0};
|
||||
|
||||
/*
|
||||
* Update the pointer to the corresponding bulk-deletion result if someone
|
||||
@@ -1127,7 +1138,7 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
|
||||
ivinfo.heaprel = pvs->heaprel;
|
||||
ivinfo.analyze_only = false;
|
||||
ivinfo.is_autovacuum = pvs->shared->is_autovacuum;
|
||||
ivinfo.report_progress = false;
|
||||
ivinfo.report_progress = true;
|
||||
ivinfo.message_level = DEBUG2;
|
||||
ivinfo.estimated_count = pvs->shared->estimated_count;
|
||||
ivinfo.num_heap_tuples = pvs->shared->reltuples;
|
||||
@@ -1137,6 +1148,13 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
|
||||
pvs->indname = pstrdup(RelationGetRelationName(indrel));
|
||||
pvs->status = indstats->status;
|
||||
|
||||
/* Report the phase and the index we're about to process */
|
||||
progress_val[0] = (indstats->status == PARALLEL_INDVAC_STATUS_NEED_BULKDELETE)
|
||||
? PROGRESS_VACUUM_PHASE_VACUUM_INDEX
|
||||
: PROGRESS_VACUUM_PHASE_INDEX_CLEANUP;
|
||||
progress_val[1] = (int64) RelationGetRelid(indrel);
|
||||
pgstat_progress_update_multi_param(2, progress_index, progress_val);
|
||||
|
||||
switch (indstats->status)
|
||||
{
|
||||
case PARALLEL_INDVAC_STATUS_NEED_BULKDELETE:
|
||||
@@ -1152,6 +1170,8 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
|
||||
RelationGetRelationName(indrel));
|
||||
}
|
||||
|
||||
pgstat_progress_update_multi_param(3, reset_index, reset_val);
|
||||
|
||||
/*
|
||||
* Copy the index bulk-deletion result returned from ambulkdelete and
|
||||
* amvacuumcleanup to the DSM segment if it's the first cycle because they
|
||||
@@ -1230,8 +1250,8 @@ parallel_vacuum_index_is_parallel_safe(Relation indrel, int num_index_scans,
|
||||
/*
|
||||
* Perform work within a launched parallel process.
|
||||
*
|
||||
* Since parallel vacuum workers perform only index vacuum or index cleanup,
|
||||
* we don't need to report progress information.
|
||||
* Parallel vacuum workers perform only index vacuum or index cleanup; they
|
||||
* report progress for the index they are processing.
|
||||
*/
|
||||
void
|
||||
parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
|
||||
@@ -1355,6 +1375,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
|
||||
/* Prepare to track buffer usage during parallel execution */
|
||||
InstrStartParallelQuery();
|
||||
|
||||
/* Register this worker for vacuum progress reporting */
|
||||
pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, shared->relid);
|
||||
|
||||
/* Process indexes to perform vacuum/cleanup */
|
||||
parallel_vacuum_process_safe_indexes(&pvs);
|
||||
|
||||
@@ -1374,6 +1397,8 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
|
||||
/* Pop the error context stack */
|
||||
error_context_stack = errcallback.previous;
|
||||
|
||||
pgstat_progress_end_command();
|
||||
|
||||
vac_close_indexes(nindexes, indrels, RowExclusiveLock);
|
||||
table_close(rel, ShareUpdateExclusiveLock);
|
||||
FreeAccessStrategy(pvs.bstrategy);
|
||||
|
||||
@@ -57,6 +57,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202609152
|
||||
#define CATALOG_VERSION_NO 202610021
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#define PROGRESS_VACUUM_DELAY_TIME 10
|
||||
#define PROGRESS_VACUUM_MODE 11
|
||||
#define PROGRESS_VACUUM_STARTED_BY 12
|
||||
#define PROGRESS_VACUUM_CURRENT_INDEX_RELID 13
|
||||
/* 15 and 16 reserved for "block number" metrics */
|
||||
|
||||
/* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
|
||||
#define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1
|
||||
|
||||
@@ -2214,7 +2214,10 @@ pg_stat_progress_vacuum| SELECT s.pid,
|
||||
WHEN 2 THEN 'autovacuum'::text
|
||||
WHEN 3 THEN 'autovacuum_wraparound'::text
|
||||
ELSE NULL::text
|
||||
END AS started_by
|
||||
END AS started_by,
|
||||
(s.param14)::oid AS current_index_relid,
|
||||
s.param16 AS index_blks_total,
|
||||
s.param17 AS index_blks_done
|
||||
FROM (pg_stat_get_progress_info('VACUUM'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
|
||||
LEFT JOIN pg_database d ON ((s.datid = d.oid)));
|
||||
pg_stat_recovery| SELECT promote_triggered,
|
||||
|
||||
Reference in New Issue
Block a user