0004-Expose-progress-for-the-vacuuming-indexes-cleanup-ph.patch
application/octet-stream
Filename: 0004-Expose-progress-for-the-vacuuming-indexes-cleanup-ph.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch 0004
Subject: Expose progress for the "vacuuming indexes/cleanup" phase of a VACUUM operation.
| File | + | − |
|---|---|---|
| doc/src/sgml/monitoring.sgml | 131 | 0 |
| src/backend/access/gin/ginvacuum.c | 4 | 0 |
| src/backend/access/gist/gistvacuum.c | 3 | 0 |
| src/backend/access/hash/hash.c | 1 | 0 |
| src/backend/access/heap/vacuumlazy.c | 11 | 0 |
| src/backend/access/nbtree/nbtree.c | 1 | 0 |
| src/backend/access/spgist/spgvacuum.c | 4 | 0 |
| src/backend/catalog/system_views.sql | 54 | 16 |
| src/backend/commands/vacuumparallel.c | 44 | 12 |
| src/include/commands/progress.h | 6 | 0 |
| src/test/regress/expected/rules.out | 50 | 13 |
From 33d4116a6b2ea4eef7d00ada279a329854514068 Mon Sep 17 00:00:00 2001
From: "Sami Imseih (AWS)"
<simseih@dev-dsk-simseih-1e-fba9b514.us-east-1.amazon.com>
Date: Thu, 27 Jan 2022 01:41:20 +0000
Subject: [PATCH 1/1] Expose progress for the "vacuuming indexes/cleanup" phase
of a VACUUM operation.
Author: Sami Imseih, based on suggestions by Nathan Bossart, Peter Geoghegan and Masahiko Sawada
Reviewed by: Nathan Bossart, Justin Pryzby
Discussion: https://www.postgresql.org/message-id/5478DFCD-2333-401A-B2F0-0D186AB09228%40amazon.com
---
doc/src/sgml/monitoring.sgml | 131 ++++++++++++++++++++++++++
src/backend/access/gin/ginvacuum.c | 4 +
src/backend/access/gist/gistvacuum.c | 3 +
src/backend/access/hash/hash.c | 1 +
src/backend/access/heap/vacuumlazy.c | 11 +++
src/backend/access/nbtree/nbtree.c | 1 +
src/backend/access/spgist/spgvacuum.c | 4 +
src/backend/catalog/system_views.sql | 70 ++++++++++----
src/backend/commands/vacuumparallel.c | 56 ++++++++---
src/include/commands/progress.h | 6 ++
src/test/regress/expected/rules.out | 63 ++++++++++---
11 files changed, 309 insertions(+), 41 deletions(-)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 62f2a3332b..b2b33acb66 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -379,6 +379,15 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
</entry>
</row>
+ <row>
+ <entry><structname>pg_stat_progress_vacuum_index</structname><indexterm><primary>pg_stat_progress_vacuum_index</primary></indexterm></entry>
+ <entry>One row for each backend (including autovacuum worker processes) running
+ the <literal>vacuuming indexes</literal> or <literal>cleaning up indexes</literal> phase of a
+ <command>VACUUM</command>, showing current progress.
+ See <xref linkend='vacuum-progress-reporting'/>.
+ </entry>
+ </row>
+
<row>
<entry><structname>pg_stat_progress_cluster</structname><indexterm><primary>pg_stat_progress_cluster</primary></indexterm></entry>
<entry>One row for each backend running
@@ -6269,6 +6278,128 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS pid,
Number of dead tuples collected since the last index vacuum cycle.
</para></entry>
</row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>index_total</structfield> <type>bigint</type>
+ </para>
+ <para>
+ The total number of indexes that will be processed by the
+ <literal>vacuuming indexes</literal> or <literal>cleaning up indexes</literal> phase
+ of vacuum.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>index_complete_count</structfield> <type>bigint</type>
+ </para>
+ <para>
+ The total number of indexes processed by the
+ <literal>vacuuming indexes</literal> or <literal>cleaning up indexes</literal> of the vacuum.
+ For vacuums with mutiple index vacuum cycles, this value will be set to <literal>0</literal>
+ at the start of each cycle.
+ </para></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <indexterm>
+ <primary>pg_stat_progress_vacuum_index</primary>
+ </indexterm>
+
+ <para>
+ Whenever <command>VACUUM</command> is running, the
+ <structname>pg_stat_progress_vacuum_index</structname> view will contain
+ one row for each backend (including autovacuum worker processes) that is
+ currently performing the <literal>vacuuming indexes</literal> or
+ <literal>cleaning up indexes</literal> phase of the vacuum.
+ </para>
+
+ <table id="pg-stat-progress-vacuum-index-view" xreflabel="pg_stat_progress_vacuum_index">
+ <title><structname>pg_stat_progress_vacuum_index</structname> View</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ Column Type
+ </para>
+ <para>
+ Description
+ </para></entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of backend.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>datid</structfield> <type>oid</type>
+ </para>
+ <para>
+ OID of the database to which this backend is connected.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>datname</structfield> <type>name</type>
+ </para>
+ <para>
+ Name of the database to which this backend is connected.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>indexrelid</structfield> <type>oid</type>
+ </para>
+ <para>
+ OID of the index being processed in the ongoing phase of the vacuum.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>phase</structfield> <type>text</type>
+ </para>
+ <para>
+ Current processing phase of a vacuum. Only the
+ <literal>vacuuming indexes</literal> or <literal>cleaning up indexes</literal>
+ phase will be listed in this view. See <xref linkend="vacuum-phases"/>.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>leader_pid</structfield> <type>integer</type>
+ </para>
+ <para>
+ Process ID of the parallel vacuum leader, if this process is a
+ parallel vacuum worker. <literal>NULL</literal> if this process is a
+ parallel vacuum leader or does not participate in parallel vacuum.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>tuples_removed</structfield> <type>oid</type>
+ </para>
+ <para>
+ The number of index tuples removed by the <literal>vacuuming indexes</literal> phase.
+ This field is <literal>0</literal> during the <literal>cleaning up indexes</literal>
+ phase.
+ </para></entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index b4fa5f6bf8..73660719b5 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -17,8 +17,10 @@
#include "access/gin_private.h"
#include "access/ginxlog.h"
#include "access/xloginsert.h"
+#include "commands/progress.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
@@ -60,6 +62,8 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items,
if (gvs->callback(items + i, gvs->callback_state))
{
gvs->result->tuples_removed += 1;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, gvs->result->tuples_removed);
+
if (!tmpitems)
{
/*
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index aac4afab8f..8a0f23388b 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -17,9 +17,11 @@
#include "access/genam.h"
#include "access/gist_private.h"
#include "access/transam.h"
+#include "commands/progress.h"
#include "commands/vacuum.h"
#include "lib/integerset.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
#include "utils/memutils.h"
@@ -375,6 +377,7 @@ restart:
END_CRIT_SECTION();
vstate->stats->tuples_removed += ntodelete;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, vstate->stats->tuples_removed);
/* must recompute maxoff */
maxoff = PageGetMaxOffsetNumber(page);
}
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index d48c8a4549..84341aa7e7 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -631,6 +631,7 @@ loop_top:
stats->estimated_count = false;
stats->num_index_tuples = num_index_tuples;
stats->tuples_removed += tuples_removed;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, stats->tuples_removed);
/* hashvacuumcleanup will fill in num_pages */
return stats;
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 1749cc2a47..432229adea 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -340,6 +340,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM,
RelationGetRelid(rel));
+ pgstat_progress_update_param(PROGRESS_VACUUM_LEADER_PID, MyProcPid);
vacuum_set_xid_limits(rel,
params->freeze_min_age,
@@ -455,6 +456,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
vacrel->FreezeLimit = FreezeLimit;
vacrel->MultiXactCutoff = MultiXactCutoff;
+ /* Advertise the total indexes to vacuum */
+ pgstat_progress_update_param(PROGRESS_VACUUM_TOTAL_INDEXES, vacrel->nindexes);
+
/*
* Call lazy_scan_heap to perform all required heap pruning, index
* vacuuming, and heap vacuuming (plus related processing)
@@ -2010,9 +2014,13 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
Relation indrel = vacrel->indrels[idx];
IndexBulkDeleteResult *istat = vacrel->indstats[idx];
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, RelationGetRelid(indrel));
vacrel->indstats[idx] =
lazy_vacuum_one_index(indrel, istat, vacrel->old_live_tuples,
vacrel);
+ pgstat_progress_update_param(PROGRESS_VACUUM_NUM_INDEX_COMPLETED, idx + 1);
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, 0);
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, 0);
if (lazy_check_wraparound_failsafe(vacrel))
{
@@ -2419,9 +2427,12 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
Relation indrel = vacrel->indrels[idx];
IndexBulkDeleteResult *istat = vacrel->indstats[idx];
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, RelationGetRelid(indrel));
vacrel->indstats[idx] =
lazy_cleanup_one_index(indrel, istat, reltuples,
estimated_count, vacrel);
+ pgstat_progress_update_param(PROGRESS_VACUUM_NUM_INDEX_COMPLETED, idx + 1);
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, 0);
}
}
else
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 13024af2fa..7455d73d13 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -1272,6 +1272,7 @@ backtrack:
nupdatable);
stats->tuples_removed += nhtidsdead;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, stats->tuples_removed);
/* must recompute maxoff */
maxoff = PageGetMaxOffsetNumber(page);
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 0049630532..db73f8ef59 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -21,8 +21,10 @@
#include "access/transam.h"
#include "access/xloginsert.h"
#include "catalog/storage_xlog.h"
+#include "commands/progress.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
@@ -160,6 +162,7 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer,
bds->stats->tuples_removed += 1;
deletable[i] = true;
nDeletable++;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, bds->stats->tuples_removed);
}
else
{
@@ -430,6 +433,7 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer)
bds->stats->tuples_removed += 1;
toDelete[xlrec.nDelete] = i;
xlrec.nDelete++;
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, bds->stats->tuples_removed);
}
else
{
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 3cb69b1f87..159605cb3f 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1113,22 +1113,60 @@ CREATE VIEW pg_stat_progress_analyze AS
LEFT JOIN pg_database D ON S.datid = D.oid;
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
- LEFT JOIN pg_database D ON S.datid = D.oid;
+ SELECT
+ S.pid,
+ S.datid,
+ S.datname,
+ S.relid,
+ S.phase,
+ S.heap_blks_total,
+ S.heap_blks_scanned,
+ S.heap_blks_vacuumed,
+ S.index_vacuum_count,
+ S.max_dead_tuples,
+ S.num_dead_tuples,
+ S.index_total,
+ S.index_complete_count
+ FROM (SELECT
+ S.pid AS pid, S.datid AS datid, D.datname AS datname,
+ S.relid AS relid, S.param12 as leader_pid,
+ 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,
+ S.param8 AS index_total,
+ CASE WHEN S.param1 IN (2,4) AND S.param9 > 0
+ AND S.param10 > 0
+ AND S.param10 > (COUNT(*) OVER (PARTITION BY S.param12) - 1)
+ THEN S.param8 - (COUNT(*) OVER (PARTITION BY S.param12) - 1)
+ ELSE SUM(S.param9) OVER(PARTITION BY S.param12)
+ END AS index_complete_count
+ FROM pg_stat_get_progress_info('VACUUM') AS S
+ LEFT JOIN pg_database D ON S.datid = D.oid) AS S
+ WHERE S.pid = S.leader_pid;
+
+CREATE VIEW pg_stat_progress_vacuum_index AS
+ SELECT
+ S.pid AS pid, S.datid AS datid,
+ D.datname AS datname,
+ S.param11 AS indexrelid,
+ CASE S.param1 WHEN 2 THEN 'vacuuming indexes'
+ WHEN 4 THEN 'cleaning up indexes'
+ END AS phase,
+ CASE WHEN S.param12 = s.pid THEN NULL
+ ELSE S.param12
+ END AS leader_pid,
+ S.param13 AS tuples_removed
+ FROM pg_stat_get_progress_info('VACUUM') AS S
+ LEFT JOIN pg_database D ON S.datid =D.oid
+ WHERE S.param1 IN (2, 4) AND S.param11 NOT IN (0);
CREATE VIEW pg_stat_progress_cluster AS
SELECT
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 974a29e7a9..eb4becf900 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -29,6 +29,7 @@
#include "access/amapi.h"
#include "access/table.h"
#include "catalog/index.h"
+#include "commands/progress.h"
#include "commands/vacuum.h"
#include "optimizer/paths.h"
#include "pgstat.h"
@@ -101,6 +102,12 @@ typedef struct PVShared
/* Counter for vacuuming and cleanup */
pg_atomic_uint32 idx;
+
+ /* Leader PID */
+ int leader_pid;
+
+ /* Number of planned parallel workers */
+ int parallel_workers;
} PVShared;
/* Status used during parallel index vacuum or cleanup */
@@ -204,10 +211,10 @@ static int parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int
bool *will_parallel_vacuum);
static void parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scans,
bool vacuum);
-static void parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs);
-static void parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs);
-static void parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
- PVIndStats *indstats);
+static void parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs, int *idx_vacuumed);
+static void parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs, int *idx_vacuumed);
+static void parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
+ PVIndStats *indstats, int *idx_vacuumed);
static bool parallel_vacuum_index_is_parallel_safe(Relation indrel, int num_index_scans,
bool vacuum);
static void parallel_vacuum_error_callback(void *arg);
@@ -259,6 +266,8 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
return NULL;
}
+ pgstat_progress_update_param(PROGRESS_VACUUM_WORKERS_PLANNED, parallel_workers);
+
pvs = (ParallelVacuumState *) palloc0(sizeof(ParallelVacuumState));
pvs->indrels = indrels;
pvs->nindexes = nindexes;
@@ -357,6 +366,8 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
(nindexes_mwm > 0) ?
maintenance_work_mem / Min(parallel_workers, nindexes_mwm) :
maintenance_work_mem;
+ shared->parallel_workers = parallel_workers;
+ shared->leader_pid = MyProcPid;
pg_atomic_init_u32(&(shared->cost_balance), 0);
pg_atomic_init_u32(&(shared->active_nworkers), 0);
@@ -565,6 +576,7 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan
{
int nworkers;
PVIndVacStatus new_status;
+ int idx_vacuumed = 0;
Assert(!IsParallelWorker());
@@ -671,13 +683,13 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan
}
/* Vacuum the indexes that can be processed by only leader process */
- parallel_vacuum_process_unsafe_indexes(pvs);
+ parallel_vacuum_process_unsafe_indexes(pvs, &idx_vacuumed);
/*
* Join as a parallel worker. The leader vacuums alone processes all
* parallel-safe indexes in the case where no workers are launched.
*/
- parallel_vacuum_process_safe_indexes(pvs);
+ parallel_vacuum_process_safe_indexes(pvs, &idx_vacuumed);
/*
* Next, accumulate buffer and WAL usage. (This must wait for the workers
@@ -723,7 +735,7 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan
* vacuum worker processes to vacuum the indexes in parallel.
*/
static void
-parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs)
+parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs, int *idx_vacuumed)
{
/*
* Increment the active worker count if we are able to launch any worker.
@@ -755,7 +767,8 @@ parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs)
continue;
/* Do vacuum or cleanup of the index */
- parallel_vacuum_process_one_index(pvs, pvs->indrels[idx], indstats);
+ parallel_vacuum_process_one_index(pvs, pvs->indrels[idx], indstats, idx_vacuumed);
+
}
/*
@@ -777,7 +790,7 @@ parallel_vacuum_process_safe_indexes(ParallelVacuumState *pvs)
* enforced by parallel_vacuum_compute_workers().
*/
static void
-parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs)
+parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs, int *idx_vacuumed)
{
Assert(!IsParallelWorker());
@@ -796,7 +809,8 @@ parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs)
continue;
/* Do vacuum or cleanup of the index */
- parallel_vacuum_process_one_index(pvs, pvs->indrels[i], indstats);
+ parallel_vacuum_process_one_index(pvs, pvs->indrels[i], indstats, idx_vacuumed);
+
}
/*
@@ -805,6 +819,7 @@ parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs)
*/
if (VacuumActiveNWorkers)
pg_atomic_sub_fetch_u32(VacuumActiveNWorkers, 1);
+
}
/*
@@ -815,7 +830,7 @@ parallel_vacuum_process_unsafe_indexes(ParallelVacuumState *pvs)
*/
static void
parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
- PVIndStats *indstats)
+ PVIndStats *indstats, int *idx_vacuumed)
{
IndexBulkDeleteResult *istat = NULL;
IndexBulkDeleteResult *istat_res;
@@ -840,13 +855,19 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
pvs->indname = pstrdup(RelationGetRelationName(indrel));
pvs->status = indstats->status;
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, RelationGetRelid(indrel));
+
switch (indstats->status)
{
case PARALLEL_INDVAC_STATUS_NEED_BULKDELETE:
+ pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_VACUUM_INDEX);
istat_res = vac_bulkdel_one_index(&ivinfo, istat, pvs->dead_items);
+ (*idx_vacuumed)++;
break;
case PARALLEL_INDVAC_STATUS_NEED_CLEANUP:
+ pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_INDEX_CLEANUP);
istat_res = vac_cleanup_one_index(&ivinfo, istat);
+ (*idx_vacuumed)++;
break;
default:
elog(ERROR, "unexpected parallel vacuum index status %d for index \"%s\"",
@@ -885,6 +906,10 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
pvs->status = PARALLEL_INDVAC_STATUS_COMPLETED;
pfree(pvs->indname);
pvs->indname = NULL;
+
+ pgstat_progress_update_param(PROGRESS_VACUUM_NUM_INDEX_COMPLETED, *idx_vacuumed);
+ pgstat_progress_update_param(PROGRESS_VACUUM_INDEXRELID, 0);
+ pgstat_progress_update_param(PROGRESS_VACUUM_TUPLES_REMOVED, 0);
}
/*
@@ -943,6 +968,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
int nindexes;
char *sharedquery;
ErrorContextCallback errcallback;
+ int idx_vacuumed = 0;
/*
* A parallel vacuum worker must have only PROC_IN_VACUUM flag since we
@@ -965,6 +991,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
* workers.
*/
rel = table_open(shared->relid, ShareUpdateExclusiveLock);
+ pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, RelationGetRelid(rel));
+ pgstat_progress_update_param(PROGRESS_VACUUM_LEADER_PID, shared->leader_pid);
+ pgstat_progress_update_param(PROGRESS_VACUUM_WORKERS_PLANNED, shared->parallel_workers);
/*
* Open all indexes. indrels are sorted in order by OID, which should be
@@ -973,6 +1002,8 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
vac_open_indexes(rel, RowExclusiveLock, &nindexes, &indrels);
Assert(nindexes > 0);
+ pgstat_progress_update_param(PROGRESS_VACUUM_TOTAL_INDEXES, nindexes);
+
if (shared->maintenance_work_mem_worker > 0)
maintenance_work_mem = shared->maintenance_work_mem_worker;
@@ -1022,7 +1053,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
InstrStartParallelQuery();
/* Process indexes to perform vacuum/cleanup */
- parallel_vacuum_process_safe_indexes(&pvs);
+ parallel_vacuum_process_safe_indexes(&pvs, &idx_vacuumed);
/* Report buffer/WAL usage during parallel execution */
buffer_usage = shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_BUFFER_USAGE, false);
@@ -1036,6 +1067,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
vac_close_indexes(nindexes, indrels, RowExclusiveLock);
table_close(rel, ShareUpdateExclusiveLock);
FreeAccessStrategy(pvs.bstrategy);
+ pgstat_progress_end_command();
}
/*
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index a28938caf4..83e74e44b3 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -25,6 +25,12 @@
#define PROGRESS_VACUUM_NUM_INDEX_VACUUMS 4
#define PROGRESS_VACUUM_MAX_DEAD_TUPLES 5
#define PROGRESS_VACUUM_NUM_DEAD_TUPLES 6
+#define PROGRESS_VACUUM_TOTAL_INDEXES 7
+#define PROGRESS_VACUUM_NUM_INDEX_COMPLETED 8
+#define PROGRESS_VACUUM_WORKERS_PLANNED 9
+#define PROGRESS_VACUUM_INDEXRELID 10
+#define PROGRESS_VACUUM_LEADER_PID 11
+#define PROGRESS_VACUUM_TUPLES_REMOVED 12
/* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
#define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index d652f7b5fb..ca2e31cd90 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2007,26 +2007,63 @@ pg_stat_progress_create_index| SELECT s.pid,
LEFT JOIN pg_database d ON ((s.datid = d.oid)));
pg_stat_progress_vacuum| SELECT s.pid,
s.datid,
- d.datname,
+ s.datname,
s.relid,
+ s.phase,
+ s.heap_blks_total,
+ s.heap_blks_scanned,
+ s.heap_blks_vacuumed,
+ s.index_vacuum_count,
+ s.max_dead_tuples,
+ s.num_dead_tuples,
+ s.index_total,
+ s.index_complete_count
+ FROM ( SELECT s_1.pid,
+ s_1.datid,
+ d.datname,
+ s_1.relid,
+ s_1.param12 AS leader_pid,
+ CASE s_1.param1
+ WHEN 0 THEN 'initializing'::text
+ WHEN 1 THEN 'scanning heap'::text
+ WHEN 2 THEN 'vacuuming indexes'::text
+ WHEN 3 THEN 'vacuuming heap'::text
+ WHEN 4 THEN 'cleaning up indexes'::text
+ WHEN 5 THEN 'truncating heap'::text
+ WHEN 6 THEN 'performing final cleanup'::text
+ ELSE NULL::text
+ END AS phase,
+ s_1.param2 AS heap_blks_total,
+ s_1.param3 AS heap_blks_scanned,
+ s_1.param4 AS heap_blks_vacuumed,
+ s_1.param5 AS index_vacuum_count,
+ s_1.param6 AS max_dead_tuples,
+ s_1.param7 AS num_dead_tuples,
+ s_1.param8 AS index_total,
+ CASE
+ WHEN ((s_1.param1 = ANY (ARRAY[(2)::bigint, (4)::bigint])) AND (s_1.param9 > 0) AND (s_1.param10 > 0) AND (s_1.param10 > (count(*) OVER (PARTITION BY s_1.param12) - 1))) THEN ((s_1.param8 - (count(*) OVER (PARTITION BY s_1.param12) - 1)))::numeric
+ ELSE sum(s_1.param9) OVER (PARTITION BY s_1.param12)
+ END AS index_complete_count
+ FROM (pg_stat_get_progress_info('VACUUM'::text) s_1(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_1.datid = d.oid)))) s
+ WHERE (s.pid = s.leader_pid);
+pg_stat_progress_vacuum_index| SELECT s.pid,
+ s.datid,
+ d.datname,
+ s.param11 AS indexrelid,
CASE s.param1
- WHEN 0 THEN 'initializing'::text
- WHEN 1 THEN 'scanning heap'::text
WHEN 2 THEN 'vacuuming indexes'::text
- WHEN 3 THEN 'vacuuming heap'::text
WHEN 4 THEN 'cleaning up indexes'::text
- WHEN 5 THEN 'truncating heap'::text
- WHEN 6 THEN 'performing final cleanup'::text
ELSE NULL::text
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
+ CASE
+ WHEN (s.param12 = s.pid) THEN NULL::bigint
+ ELSE s.param12
+ END AS leader_pid,
+ s.param13 AS tuples_removed
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)));
+ LEFT JOIN pg_database d ON ((s.datid = d.oid)))
+ WHERE ((s.param1 = ANY (ARRAY[(2)::bigint, (4)::bigint])) AND (s.param11 <> 0));
pg_stat_replication| SELECT s.pid,
s.usesysid,
u.rolname AS usename,
--
2.32.0