Skip to content

Commit 1b3d2a6

Browse files
BRupireddy2hackorum
authored andcommitted
Report indexes being vacuumed in pg_stat_progress_vacuum
Previously, during the "vacuuming indexes" and "cleaning up indexes" phases, pg_stat_progress_vacuum reported how many indexes had been processed but not which index was being processed. On a table with many indexes, especially indexes of different types, this made it hard to tell which index a slow or stuck vacuum was working on. This commit adds two columns to pg_stat_progress_vacuum, index_vacuum_pids and index_vacuum_oids. Each process, the leader and any parallel workers, reports the OID of the index it is currently processing into its own progress array slot. The view gathers these onto the leader's row as two arrays that are aligned by position, so that unnest(index_vacuum_pids, index_vacuum_oids) gives the (pid, index) pairs. For a serial vacuum each array holds a single value, and both are null when no index is being processed. Because pg_stat_progress_vacuum reports one row per command, the per-worker information is aggregated onto the leader's row rather than shown as separate rows. This needs no new shared memory, since the per-process progress array slots already exist. Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> Reviewed-by: Sami Imseih <samimseih@gmail.com> Reviewed-by: Satyanarayana Narlapuram <satyanarlapuram@gmail.com> Discussion: https://postgr.es/m/CALj2ACUgwSchK6jQ2CdKLBWUADTOE_zKdTff2Zg3E6hOuXKv-w@mail.gmail.com
1 parent 44056f6 commit 1b3d2a6

6 files changed

Lines changed: 93 additions & 5 deletions

File tree

doc/src/sgml/monitoring.sgml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7892,6 +7892,29 @@ FROM pg_stat_get_backend_idset() AS backendid;
78927892
</itemizedlist>
78937893
</para></entry>
78947894
</row>
7895+
7896+
<row>
7897+
<entry role="catalog_table_entry"><para role="column_definition">
7898+
<structfield>index_vacuum_pids</structfield> <type>integer[]</type>
7899+
</para>
7900+
<para>
7901+
The process IDs currently vacuuming or cleaning up an index (the
7902+
leader process and any parallel workers). Null when no index is
7903+
being processed.
7904+
</para></entry>
7905+
</row>
7906+
7907+
<row>
7908+
<entry role="catalog_table_entry"><para role="column_definition">
7909+
<structfield>index_vacuum_oids</structfield> <type>oid[]</type>
7910+
</para>
7911+
<para>
7912+
The OIDs of the indexes being vacuumed or cleaned up, aligned by
7913+
position with <structfield>index_vacuum_pids</structfield>: the index
7914+
at each position is being processed by the process ID at the same
7915+
position. Null when no index is being processed.
7916+
</para></entry>
7917+
</row>
78957918
</tbody>
78967919
</tgroup>
78977920
</table>

src/backend/access/heap/vacuumlazy.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,6 +3044,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
30443044
ivinfo.num_heap_tuples = reltuples;
30453045
ivinfo.strategy = vacrel->bstrategy;
30463046

3047+
/* Report which index we're currently processing */
3048+
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
3049+
RelationGetRelid(indrel));
3050+
30473051
/*
30483052
* Update error traceback information.
30493053
*
@@ -3065,6 +3069,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
30653069
pfree(vacrel->indname);
30663070
vacrel->indname = NULL;
30673071

3072+
/* Reset the current index relid */
3073+
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
3074+
InvalidOid);
3075+
30683076
return istat;
30693077
}
30703078

@@ -3095,6 +3103,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
30953103
ivinfo.num_heap_tuples = reltuples;
30963104
ivinfo.strategy = vacrel->bstrategy;
30973105

3106+
/* Report which index we're currently processing */
3107+
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
3108+
RelationGetRelid(indrel));
3109+
30983110
/*
30993111
* Update error traceback information.
31003112
*
@@ -3114,6 +3126,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
31143126
pfree(vacrel->indname);
31153127
vacrel->indname = NULL;
31163128

3129+
/* Reset the current index relid */
3130+
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
3131+
InvalidOid);
3132+
31173133
return istat;
31183134
}
31193135

src/backend/catalog/system_views.sql

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,9 +1353,26 @@ CREATE VIEW pg_stat_progress_vacuum AS
13531353
CASE S.param13 WHEN 1 THEN 'manual'
13541354
WHEN 2 THEN 'autovacuum'
13551355
WHEN 3 THEN 'autovacuum_wraparound'
1356-
ELSE NULL END AS started_by
1356+
ELSE NULL END AS started_by,
1357+
I.index_vacuum_pids AS index_vacuum_pids,
1358+
I.index_vacuum_oids AS index_vacuum_oids
13571359
FROM pg_stat_get_progress_info('VACUUM') AS S
1358-
LEFT JOIN pg_database D ON S.datid = D.oid;
1360+
LEFT JOIN pg_database D ON S.datid = D.oid
1361+
LEFT JOIN pg_stat_activity A ON S.pid = A.pid,
1362+
LATERAL (
1363+
-- Aggregate the indexes being processed by this vacuum's leader
1364+
-- and its parallel workers (if any) into the single leader row.
1365+
-- Both arrays use the same ORDER BY so that they stay aligned by
1366+
-- position; the leader is listed first when it is itself
1367+
-- processing an index.
1368+
SELECT array_agg(W.pid ORDER BY W.pid <> S.pid, W.pid) AS index_vacuum_pids,
1369+
array_agg(CAST(W.param14 AS oid) ORDER BY W.pid <> S.pid, W.pid) AS index_vacuum_oids
1370+
FROM pg_stat_get_progress_info('VACUUM') AS W
1371+
LEFT JOIN pg_stat_activity WA ON W.pid = WA.pid
1372+
WHERE COALESCE(WA.leader_pid, W.pid) = S.pid
1373+
AND W.param14 <> 0
1374+
) I
1375+
WHERE A.leader_pid IS NULL;
13591376

13601377
CREATE VIEW pg_stat_progress_repack AS
13611378
SELECT

src/backend/commands/vacuumparallel.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,11 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
10761076
IndexBulkDeleteResult *istat = NULL;
10771077
IndexBulkDeleteResult *istat_res;
10781078
IndexVacuumInfo ivinfo;
1079+
const int progress_index[] = {
1080+
PROGRESS_VACUUM_PHASE,
1081+
PROGRESS_VACUUM_CURRENT_INDEX_RELID
1082+
};
1083+
int64 progress_val[2];
10791084

10801085
/*
10811086
* Update the pointer to the corresponding bulk-deletion result if someone
@@ -1097,6 +1102,13 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
10971102
pvs->indname = pstrdup(RelationGetRelationName(indrel));
10981103
pvs->status = indstats->status;
10991104

1105+
/* Report which index we're currently processing and the current phase */
1106+
progress_val[0] = (indstats->status == PARALLEL_INDVAC_STATUS_NEED_BULKDELETE)
1107+
? PROGRESS_VACUUM_PHASE_VACUUM_INDEX
1108+
: PROGRESS_VACUUM_PHASE_INDEX_CLEANUP;
1109+
progress_val[1] = RelationGetRelid(indrel);
1110+
pgstat_progress_update_multi_param(2, progress_index, progress_val);
1111+
11001112
switch (indstats->status)
11011113
{
11021114
case PARALLEL_INDVAC_STATUS_NEED_BULKDELETE:
@@ -1144,6 +1156,10 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
11441156
pfree(pvs->indname);
11451157
pvs->indname = NULL;
11461158

1159+
/* Reset the current index relid */
1160+
pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
1161+
InvalidOid);
1162+
11471163
/*
11481164
* Call the parallel variant of pgstat_progress_incr_param so workers can
11491165
* report progress of index vacuum to the leader.
@@ -1315,6 +1331,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
13151331
/* Prepare to track buffer usage during parallel execution */
13161332
InstrStartParallelQuery();
13171333

1334+
/* Register this worker for vacuum progress reporting */
1335+
pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, shared->relid);
1336+
13181337
/* Process indexes to perform vacuum/cleanup */
13191338
parallel_vacuum_process_safe_indexes(&pvs);
13201339

@@ -1334,6 +1353,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
13341353
/* Pop the error context stack */
13351354
error_context_stack = errcallback.previous;
13361355

1356+
/* Unregister this worker from vacuum progress reporting */
1357+
pgstat_progress_end_command();
1358+
13371359
vac_close_indexes(nindexes, indrels, RowExclusiveLock);
13381360
table_close(rel, ShareUpdateExclusiveLock);
13391361
FreeAccessStrategy(pvs.bstrategy);

src/include/commands/progress.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define PROGRESS_VACUUM_DELAY_TIME 10
3232
#define PROGRESS_VACUUM_MODE 11
3333
#define PROGRESS_VACUUM_STARTED_BY 12
34+
#define PROGRESS_VACUUM_CURRENT_INDEX_RELID 13
3435

3536
/* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
3637
#define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1

src/test/regress/expected/rules.out

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,9 +2213,18 @@ pg_stat_progress_vacuum| SELECT s.pid,
22132213
WHEN 2 THEN 'autovacuum'::text
22142214
WHEN 3 THEN 'autovacuum_wraparound'::text
22152215
ELSE NULL::text
2216-
END AS started_by
2217-
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)
2218-
LEFT JOIN pg_database d ON ((s.datid = d.oid)));
2216+
END AS started_by,
2217+
i.index_vacuum_pids,
2218+
i.index_vacuum_oids
2219+
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)
2220+
LEFT JOIN pg_database d ON ((s.datid = d.oid)))
2221+
LEFT JOIN pg_stat_activity a ON ((s.pid = a.pid))),
2222+
LATERAL ( SELECT array_agg(w.pid ORDER BY (w.pid <> s.pid), w.pid) AS index_vacuum_pids,
2223+
array_agg((w.param14)::oid ORDER BY (w.pid <> s.pid), w.pid) AS index_vacuum_oids
2224+
FROM (pg_stat_get_progress_info('VACUUM'::text) w(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
2225+
LEFT JOIN pg_stat_activity wa ON ((w.pid = wa.pid)))
2226+
WHERE ((COALESCE(wa.leader_pid, w.pid) = s.pid) AND (w.param14 <> 0))) i
2227+
WHERE (a.leader_pid IS NULL);
22192228
pg_stat_recovery| SELECT promote_triggered,
22202229
last_replayed_read_lsn,
22212230
last_replayed_end_lsn,

0 commit comments

Comments
 (0)