Hi,
On Tue, Aug 25, 2026 at 9:34 AM Bharath Rupireddy
<[email protected]> wrote:
>
> Hi,
>
> On Thu, Aug 20, 2026 at 4:10 PM Michael Paquier <[email protected]> wrote:
> >
> > On Wed, Aug 19, 2026 at 07:37:00PM -0700, Bharath Rupireddy wrote:
> > > I don't think a separate view is the right approach at least for two
> > > reasons. One, to know the progress of a vacuum one has to query two
> > > views and relate them. Two, since the leader itself participates in
> > > vacuuming indexes alongside workers (and will also for parallel heap
> > > vacuum), splitting the same command's progress into two views adds
> > > complexity. Keeping everything in a single view with one row per
> > > worker (as discussed upthread) is simpler. Some fields would be null
> > > on worker rows, but documenting this should be sufficient. That said,
> > > I'm open to hear more thoughts on this.
> >
> > Having a single progress view feels like the natural approach here,
> > for both the leader and the workers. The leader triggers the
> > existence of the workers, but both leader and workers may finish by
> > doing the same job as there could be usually little meaning for a
> > leader to stand idle, waiting for all the workers to do the work.
> > Such choices are implementation-agnostic, of course; we should not
> > lock ourselves.
>
> Thanks for reviewing. After thinking about this for a while, I still
> think one row per worker is the better choice, with the tradeoff of
> some fields being null on worker rows (similar to leader_pid in
> pg_stat_activity). The docs also say "the view will contain one row
> for each backend that is currently vacuuming," and in that sense,
> parallel workers launched for index vacuum are essentially doing
> vacuum too.
>
> Here's what I have. 0001 reports the current index being vacuumed, and
> 0002 reports the total blocks and done blocks for B-tree indexes. This
> helps track vacuum progress for large indexes in production.
>
> Please have a look.
Thanks Michael for the off-list chat. I agree that emitting leader_pid
via the vacuum progress report is information bloat, since one can
easily identify the workers for a given leader by looking at the
database OID and relation name, and if needed, can also join with
pg_stat_activity.leader_pid. So, I removed leader_pid in the 0001
patch.
Please find the attached v5 patches.
Here is some sample output that I captured:
-- Test 1: manual VACUUM, non-parallel index vacuum.
-- Take 1
pid | datid | datname | relid | phase |
heap_blks_scanned | current_index | index_blks_total | index_blks_done
| started_by
------+-------+----------+----------+-------------------+-------------------+---------------+------------------+-----------------+------------
5786 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 3706 | manual
-- Take 2
5786 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 10275 | manual
-- Test 2: manual VACUUM (PARALLEL 2), parallel index vacuum.
-- Take 1
pid | datid | datname | relid | phase |
heap_blks_scanned | current_index | index_blks_total | index_blks_done
| started_by
------+-------+----------+----------+-------------------+-------------------+---------------+------------------+-----------------+------------
8040 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 463 | manual
8372 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx3 | 27422 | 399 |
8373 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx2 | 27422 | 351 |
-- Take 2
8040 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 9855 | manual
8372 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx3 | 27422 | 9199 |
8373 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx2 | 27422 | 9145 |
-- Test 3: autovacuum, non-parallel index vacuum.
-- Take 1
pid | datid | datname | relid | phase |
heap_blks_scanned | current_index | index_blks_total | index_blks_done
| started_by
------+-------+----------+----------+-------------------+-------------------+---------------+------------------+-----------------+------------
9835 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 1023 |
autovacuum
-- Take 2
9835 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 3071 |
autovacuum
-- Test 4: autovacuum, parallel index vacuum (autovacuum_parallel_workers=2).
-- Take 1
pid | datid | datname | relid | phase |
heap_blks_scanned | current_index | index_blks_total | index_blks_done
| started_by
-------+-------+----------+----------+-------------------+-------------------+---------------+------------------+-----------------+------------
31309 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 459 |
autovacuum
650 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx2 | 27422 | 476 |
651 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx3 | 27422 | 474 |
-- Take 2
31309 | 5 | postgres | test_vac | vacuuming indexes |
63695 | test_vac_idx1 | 27422 | 2115 |
autovacuum
650 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx2 | 27422 | 2126 |
651 | 5 | postgres | test_vac | vacuuming indexes |
0 | test_vac_idx3 | 27422 | 2118 |
--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
From 40dd523966ec6032acd73382063875fc3b31a46f Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Wed, 2 Sep 2026 23:24:10 +0000
Subject: [PATCH v5 1/2] Report the index being vacuumed in
pg_stat_progress_vacuum.
Previously, pg_stat_progress_vacuum showed the total and processed
index counts, but not which index a backend was actually working on.
On a table with many indexes of different access methods, this made
it hard to tell which index a slow or stuck vacuum was spending its
time on.
This commit adds a current_index_relid column reporting the OID of
the index a backend is currently vacuuming or cleaning up. It is set
before each index is processed and reset once that index is done, so
it does not report a stale value after the phase moves on.
During parallel index vacuum the leader also participates, and each
participant processes a different set of indexes. That per-index
progress cannot be collapsed into a single leader row without losing
the detail that matters, so each participant, the leader and the
workers alike, now reports its own row and shows the index it is
processing. A worker row carries the columns that come from its own
backend state, pid, datid, datname, relid, phase and
current_index_relid; the remaining columns track command-level heap
progress that only the leader maintains and read as zero on worker
rows. Because a table can be vacuumed by only one VACUUM at a time,
the rows sharing a datid and relid make up a single vacuum, so they
can be grouped that way to see the leader together with all of its
workers. If the exact leader-to-worker mapping is wanted, it can be
recovered from leader_pid in pg_stat_activity.
Author: Bharath Rupireddy <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Reviewed-by: Sami Imseih <[email protected]>
Reviewed-by: Satyanarayana Narlapuram <[email protected]>
Discussion: https://postgr.es/m/CALj2ACUgwSchK6jQ2CdKLBWUADTOE_zKdTff2Zg3E6hOuXKv-w@mail.gmail.com
---
doc/src/sgml/monitoring.sgml | 47 +++++++++++++++++++++++++--
src/backend/access/heap/vacuumlazy.c | 16 +++++++++
src/backend/catalog/system_views.sql | 3 +-
src/backend/commands/vacuumparallel.c | 25 ++++++++++++++
src/include/commands/progress.h | 1 +
src/test/regress/expected/rules.out | 3 +-
6 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index b403fb990a7..e39f9637775 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -7651,8 +7651,11 @@ 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; see the note following the view for the columns reported on
+ parallel worker rows. 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
@@ -7910,10 +7913,50 @@ 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>
+ If <command>VACUUM</command> is currently processing an index, this
+ column shows the OID of the index being vacuumed. The value is set
+ when the phase is <literal>vacuuming indexes</literal> or
+ <literal>cleaning up indexes</literal> and is reset to 0 when all
+ indexes have been processed. During parallel index vacuum, each
+ parallel worker row shows the index that particular worker is
+ processing.
+ </para></entry>
+ </row>
+
</tbody>
</tgroup>
</table>
+ <note>
+ <para>
+ During a parallel vacuum, each participating backend (the leader and each
+ parallel worker) reports its own row. On a worker row the meaningful
+ columns are <structfield>pid</structfield>, <structfield>datid</structfield>,
+ <structfield>datname</structfield>, <structfield>relid</structfield>,
+ <structfield>phase</structfield> and
+ <structfield>current_index_relid</structfield>. The remaining columns track
+ command-level heap progress that only the leader maintains; they read as
+ zero on worker rows. Because a table can be vacuumed by only one
+ <command>VACUUM</command> at a time, the rows sharing a given
+ <structfield>datid</structfield> and <structfield>relid</structfield>
+ together make up a single vacuum, so they can be grouped that way to see
+ the leader and all of its workers. The leader and worker process IDs can be
+ correlated with <structfield>leader_pid</structfield> in
+ <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+ if needed. Because the worker rows are separate backends, a role that does
+ not have privileges of the <literal>pg_read_all_stats</literal> role and
+ does not own those backends sees only their <structfield>pid</structfield>,
+ with the remaining columns <literal>NULL</literal>, just as in
+ <structname>pg_stat_activity</structname>.
+ </para>
+ </note>
+
<table id="vacuum-phases">
<title>VACUUM Phases</title>
<tgroup cols="2">
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 063ef2208de..8bc3de84581 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -3048,6 +3048,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
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.
*
@@ -3069,6 +3073,10 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
+ /* Reset the current index relid to avoid reporting a stale value */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) InvalidOid);
+
return istat;
}
@@ -3099,6 +3107,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
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.
*
@@ -3118,6 +3130,10 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
+ /* Reset the current index relid to avoid reporting a stale value */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) InvalidOid);
+
return istat;
}
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8612d99a890..24d2ae8bb44 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1353,7 +1353,8 @@ 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
FROM pg_stat_get_progress_info('VACUUM') AS S
LEFT JOIN pg_database D ON S.datid = D.oid;
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 767d162e578..d6a56f63a0f 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -1076,6 +1076,11 @@ 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];
/*
* Update the pointer to the corresponding bulk-deletion result if someone
@@ -1097,6 +1102,16 @@ 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 before we start,
+ * so that it is visible for the whole duration of the index scan.
+ */
+ 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:
@@ -1112,6 +1127,10 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
RelationGetRelationName(indrel));
}
+ /* Reset the current index relid to avoid reporting a stale value */
+ pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
+ (int64) InvalidOid);
+
/*
* Copy the index bulk-deletion result returned from ambulkdelete and
* amvacuumcleanup to the DSM segment if it's the first cycle because they
@@ -1315,6 +1334,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);
@@ -1334,6 +1356,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
/* Pop the error context stack */
error_context_stack = errcallback.previous;
+ /* Unregister this worker from vacuum progress reporting */
+ pgstat_progress_end_command();
+
vac_close_indexes(nindexes, indrels, RowExclusiveLock);
table_close(rel, ShareUpdateExclusiveLock);
FreeAccessStrategy(pvs.bstrategy);
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index 2a12920c75f..bee311955b6 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -31,6 +31,7 @@
#define PROGRESS_VACUUM_DELAY_TIME 10
#define PROGRESS_VACUUM_MODE 11
#define PROGRESS_VACUUM_STARTED_BY 12
+#define PROGRESS_VACUUM_CURRENT_INDEX_RELID 13
/* 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 1a29d46213e..cf9b8c823c8 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2213,7 +2213,8 @@ 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
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,
--
2.47.3
From 249378140e1016436401da4f117cb5efeab9351e Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Wed, 2 Sep 2026 23:27:23 +0000
Subject: [PATCH v5 2/2] Report index block progress in
pg_stat_progress_vacuum.
Previously, pg_stat_progress_vacuum reported which index a backend
was vacuuming but not how far it had gotten through that index. This
matters most for B-tree, the common index type: for a large B-tree,
at the scale of hundreds of GBs to TBs, per-index progress is what
lets one estimate when the index phase, and together with
heap_blks_* the whole vacuum, will finish.
This commit reuses the block counters that CREATE INDEX progress
reporting added in commit ab0dfc961 (PROGRESS_SCAN_BLOCKS_TOTAL and
PROGRESS_SCAN_BLOCKS_DONE), exposing them as new index_blks_total
and index_blks_done columns. B-tree's bulk-delete scan already knows
how to report them, so this commit only turns that reporting on in
the serial and parallel index-vacuum paths. Like current_index_relid,
the counters are reported per participating backend, so each worker's
row shows progress for the index it is scanning.
These counters are kept separate from heap_blks_*. The heap block
counters must be retained across a multi-pass index vacuum, which
happens when the dead-TID store fills, and in the serial case the
leader does the index vacuuming itself, so reusing the heap counters
for index blocks would corrupt heap progress that is still needed.
No caller sets IndexVacuumInfo.report_progress to false anymore;
removing it is parked for a follow-up commit.
Author: Bharath Rupireddy <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Reviewed-by: Sami Imseih <[email protected]>
Discussion: https://postgr.es/m/CALj2ACX6gyBmQfaqbCsycDmaSPbq1=iPJw1OqUT+aLqaKjW8dQ@mail.gmail.com
---
doc/src/sgml/monitoring.sgml | 28 +++++++++++++++++++++--
src/backend/access/heap/vacuumlazy.c | 32 ++++++++++++++++++++-------
src/backend/catalog/system_views.sql | 4 +++-
src/backend/commands/vacuumparallel.c | 16 ++++++++++----
src/test/regress/expected/rules.out | 4 +++-
5 files changed, 68 insertions(+), 16 deletions(-)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index e39f9637775..d7f6a83edfd 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -7929,6 +7929,29 @@ FROM pg_stat_get_backend_idset() AS backendid;
</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 to scan for the B-tree index identified by
+ <structfield>current_index_relid</structfield>. It is reset to 0 once
+ the index has been processed.
+ </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 scanned so far for the B-tree index identified by
+ <structfield>current_index_relid</structfield>. Together with
+ <structfield>index_blks_total</structfield> this gives per-index vacuum
+ progress, which is useful for estimating completion of large indexes.
+ </para></entry>
+ </row>
+
</tbody>
</tgroup>
</table>
@@ -7939,8 +7962,9 @@ FROM pg_stat_get_backend_idset() AS backendid;
parallel worker) reports its own row. On a worker row the meaningful
columns are <structfield>pid</structfield>, <structfield>datid</structfield>,
<structfield>datname</structfield>, <structfield>relid</structfield>,
- <structfield>phase</structfield> and
- <structfield>current_index_relid</structfield>. The remaining columns track
+ <structfield>phase</structfield>, <structfield>current_index_relid</structfield>,
+ <structfield>index_blks_total</structfield> and
+ <structfield>index_blks_done</structfield>. The remaining columns track
command-level heap progress that only the leader maintains; they read as
zero on worker rows. Because a table can be vacuumed by only one
<command>VACUUM</command> at a time, the rows sharing a given
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 8bc3de84581..459fff8df1d 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -3038,11 +3038,17 @@ 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.report_progress = false;
+ ivinfo.report_progress = true;
ivinfo.estimated_count = true;
ivinfo.message_level = DEBUG2;
ivinfo.num_heap_tuples = reltuples;
@@ -3073,9 +3079,11 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
- /* Reset the current index relid to avoid reporting a stale value */
- pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
- (int64) InvalidOid);
+ /*
+ * Reset the current index progress parameters to avoid reporting stale
+ * values.
+ */
+ pgstat_progress_update_multi_param(3, reset_index, reset_val);
return istat;
}
@@ -3096,11 +3104,17 @@ 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.report_progress = false;
+ ivinfo.report_progress = true;
ivinfo.estimated_count = estimated_count;
ivinfo.message_level = DEBUG2;
@@ -3130,9 +3144,11 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
pfree(vacrel->indname);
vacrel->indname = NULL;
- /* Reset the current index relid to avoid reporting a stale value */
- pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
- (int64) InvalidOid);
+ /*
+ * Reset the current index progress parameters to avoid reporting stale
+ * values.
+ */
+ pgstat_progress_update_multi_param(3, reset_index, reset_val);
return istat;
}
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 24d2ae8bb44..f29e2767154 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1354,7 +1354,9 @@ CREATE VIEW pg_stat_progress_vacuum AS
WHEN 2 THEN 'autovacuum'
WHEN 3 THEN 'autovacuum_wraparound'
ELSE NULL END AS started_by,
- CAST(S.param14 AS oid) AS current_index_relid
+ 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;
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index d6a56f63a0f..be87b1937ad 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -1081,6 +1081,12 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
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
@@ -1092,7 +1098,7 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
ivinfo.index = indrel;
ivinfo.heaprel = pvs->heaprel;
ivinfo.analyze_only = false;
- 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;
@@ -1127,9 +1133,11 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
RelationGetRelationName(indrel));
}
- /* Reset the current index relid to avoid reporting a stale value */
- pgstat_progress_update_param(PROGRESS_VACUUM_CURRENT_INDEX_RELID,
- (int64) InvalidOid);
+ /*
+ * Reset the current index progress parameters to avoid reporting stale
+ * values.
+ */
+ pgstat_progress_update_multi_param(3, reset_index, reset_val);
/*
* Copy the index bulk-deletion result returned from ambulkdelete and
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index cf9b8c823c8..475604289de 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2214,7 +2214,9 @@ pg_stat_progress_vacuum| SELECT s.pid,
WHEN 3 THEN 'autovacuum_wraparound'::text
ELSE NULL::text
END AS started_by,
- (s.param14)::oid AS current_index_relid
+ (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,
--
2.47.3