@@ -315,6 +315,10 @@ typedef struct LVRelStats
315315 TransactionId latestRemovedXid ;
316316 bool lock_waiter_detected ;
317317
318+ /* Statistics about indexes */
319+ IndexBulkDeleteResult * * indstats ;
320+ int nindexes ;
321+
318322 /* Used for error callback */
319323 char * indname ;
320324 BlockNumber blkno ; /* used only for heap operations */
@@ -348,7 +352,6 @@ static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
348352static bool lazy_check_needs_freeze (Buffer buf , bool * hastup ,
349353 LVRelStats * vacrelstats );
350354static void lazy_vacuum_all_indexes (Relation onerel , Relation * Irel ,
351- IndexBulkDeleteResult * * stats ,
352355 LVRelStats * vacrelstats , LVParallelState * lps ,
353356 int nindexes );
354357static void lazy_vacuum_index (Relation indrel , IndexBulkDeleteResult * * stats ,
@@ -371,21 +374,18 @@ static int vac_cmp_itemptr(const void *left, const void *right);
371374static bool heap_page_is_all_visible (Relation rel , Buffer buf ,
372375 LVRelStats * vacrelstats ,
373376 TransactionId * visibility_cutoff_xid , bool * all_frozen );
374- static void lazy_parallel_vacuum_indexes (Relation * Irel , IndexBulkDeleteResult * * stats ,
375- LVRelStats * vacrelstats , LVParallelState * lps ,
376- int nindexes );
377- static void parallel_vacuum_index (Relation * Irel , IndexBulkDeleteResult * * stats ,
378- LVShared * lvshared , LVDeadTuples * dead_tuples ,
379- int nindexes , LVRelStats * vacrelstats );
380- static void vacuum_indexes_leader (Relation * Irel , IndexBulkDeleteResult * * stats ,
381- LVRelStats * vacrelstats , LVParallelState * lps ,
382- int nindexes );
377+ static void lazy_parallel_vacuum_indexes (Relation * Irel , LVRelStats * vacrelstats ,
378+ LVParallelState * lps , int nindexes );
379+ static void parallel_vacuum_index (Relation * Irel , LVShared * lvshared ,
380+ LVDeadTuples * dead_tuples , int nindexes ,
381+ LVRelStats * vacrelstats );
382+ static void vacuum_indexes_leader (Relation * Irel , LVRelStats * vacrelstats ,
383+ LVParallelState * lps , int nindexes );
383384static void vacuum_one_index (Relation indrel , IndexBulkDeleteResult * * stats ,
384385 LVShared * lvshared , LVSharedIndStats * shared_indstats ,
385386 LVDeadTuples * dead_tuples , LVRelStats * vacrelstats );
386- static void lazy_cleanup_all_indexes (Relation * Irel , IndexBulkDeleteResult * * stats ,
387- LVRelStats * vacrelstats , LVParallelState * lps ,
388- int nindexes );
387+ static void lazy_cleanup_all_indexes (Relation * Irel , LVRelStats * vacrelstats ,
388+ LVParallelState * lps , int nindexes );
389389static long compute_max_dead_tuples (BlockNumber relblocks , bool hasindex );
390390static int compute_parallel_vacuum_workers (Relation * Irel , int nindexes , int nrequested ,
391391 bool * can_parallel_vacuum );
@@ -433,6 +433,7 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
433433 write_rate ;
434434 bool aggressive ; /* should we scan all unfrozen pages? */
435435 bool scanned_all_unfrozen ; /* actually scanned all such pages? */
436+ char * * indnames = NULL ;
436437 TransactionId xidFullScanLimit ;
437438 MultiXactId mxactFullScanLimit ;
438439 BlockNumber new_rel_pages ;
@@ -512,6 +513,20 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
512513 vacrelstats -> useindex = (nindexes > 0 &&
513514 params -> index_cleanup == VACOPT_TERNARY_ENABLED );
514515
516+ vacrelstats -> indstats = (IndexBulkDeleteResult * * )
517+ palloc0 (nindexes * sizeof (IndexBulkDeleteResult * ));
518+ vacrelstats -> nindexes = nindexes ;
519+
520+ /* Save index names iff autovacuum logging requires it */
521+ if (IsAutoVacuumWorkerProcess () &&
522+ params -> log_min_duration >= 0 &&
523+ vacrelstats -> nindexes > 0 )
524+ {
525+ indnames = palloc (sizeof (char * ) * vacrelstats -> nindexes );
526+ for (int i = 0 ; i < vacrelstats -> nindexes ; i ++ )
527+ indnames [i ] = pstrdup (RelationGetRelationName (Irel [i ]));
528+ }
529+
515530 /*
516531 * Setup error traceback support for ereport(). The idea is to set up an
517532 * error context callback to display additional information on any error
@@ -680,6 +695,21 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
680695 (long long ) VacuumPageHit ,
681696 (long long ) VacuumPageMiss ,
682697 (long long ) VacuumPageDirty );
698+ for (int i = 0 ; i < vacrelstats -> nindexes ; i ++ )
699+ {
700+ IndexBulkDeleteResult * stats = vacrelstats -> indstats [i ];
701+
702+ if (!stats )
703+ continue ;
704+
705+ appendStringInfo (& buf ,
706+ _ ("index \"%s\": pages: %u remain, %u newly deleted, %u currently deleted, %u reusable\n" ),
707+ indnames [i ],
708+ stats -> num_pages ,
709+ stats -> pages_newly_deleted ,
710+ stats -> pages_deleted ,
711+ stats -> pages_free );
712+ }
683713 appendStringInfo (& buf , _ ("avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" ),
684714 read_rate , write_rate );
685715 if (track_io_timing )
@@ -705,6 +735,16 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
705735 pfree (buf .data );
706736 }
707737 }
738+
739+ /* Cleanup index statistics and index names */
740+ for (int i = 0 ; i < vacrelstats -> nindexes ; i ++ )
741+ {
742+ if (vacrelstats -> indstats [i ])
743+ pfree (vacrelstats -> indstats [i ]);
744+
745+ if (indnames && indnames [i ])
746+ pfree (indnames [i ]);
747+ }
708748}
709749
710750/*
@@ -787,7 +827,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
787827 tups_vacuumed , /* tuples cleaned up by current vacuum */
788828 nkeep , /* dead-but-not-removable tuples */
789829 nunused ; /* # existing unused line pointers */
790- IndexBulkDeleteResult * * indstats ;
791830 int i ;
792831 PGRUsage ru0 ;
793832 Buffer vmbuffer = InvalidBuffer ;
@@ -820,9 +859,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
820859 next_fsm_block_to_vacuum = (BlockNumber ) 0 ;
821860 num_tuples = live_tuples = tups_vacuumed = nkeep = nunused = 0 ;
822861
823- indstats = (IndexBulkDeleteResult * * )
824- palloc0 (nindexes * sizeof (IndexBulkDeleteResult * ));
825-
826862 nblocks = RelationGetNumberOfBlocks (onerel );
827863 vacrelstats -> rel_pages = nblocks ;
828864 vacrelstats -> scanned_pages = 0 ;
@@ -1070,8 +1106,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
10701106 }
10711107
10721108 /* Work on all the indexes, then the heap */
1073- lazy_vacuum_all_indexes (onerel , Irel , indstats ,
1074- vacrelstats , lps , nindexes );
1109+ lazy_vacuum_all_indexes (onerel , Irel , vacrelstats , lps , nindexes );
10751110
10761111 /* Remove tuples from heap */
10771112 lazy_vacuum_heap (onerel , vacrelstats );
@@ -1728,8 +1763,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
17281763 if (dead_tuples -> num_tuples > 0 )
17291764 {
17301765 /* Work on all the indexes, and then the heap */
1731- lazy_vacuum_all_indexes (onerel , Irel , indstats , vacrelstats ,
1732- lps , nindexes );
1766+ lazy_vacuum_all_indexes (onerel , Irel , vacrelstats , lps , nindexes );
17331767
17341768 /* Remove tuples from heap */
17351769 lazy_vacuum_heap (onerel , vacrelstats );
@@ -1747,18 +1781,18 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
17471781
17481782 /* Do post-vacuum cleanup */
17491783 if (vacrelstats -> useindex )
1750- lazy_cleanup_all_indexes (Irel , indstats , vacrelstats , lps , nindexes );
1784+ lazy_cleanup_all_indexes (Irel , vacrelstats , lps , nindexes );
17511785
17521786 /*
17531787 * End parallel mode before updating index statistics as we cannot write
17541788 * during parallel mode.
17551789 */
17561790 if (ParallelVacuumIsActive (lps ))
1757- end_parallel_vacuum (indstats , lps , nindexes );
1791+ end_parallel_vacuum (vacrelstats -> indstats , lps , nindexes );
17581792
17591793 /* Update index statistics */
17601794 if (vacrelstats -> useindex )
1761- update_index_statistics (Irel , indstats , nindexes );
1795+ update_index_statistics (Irel , vacrelstats -> indstats , nindexes );
17621796
17631797 /* If no indexes, make log report that lazy_vacuum_heap would've made */
17641798 if (vacuumed_pages )
@@ -1803,7 +1837,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
18031837 */
18041838static void
18051839lazy_vacuum_all_indexes (Relation onerel , Relation * Irel ,
1806- IndexBulkDeleteResult * * stats ,
18071840 LVRelStats * vacrelstats , LVParallelState * lps ,
18081841 int nindexes )
18091842{
@@ -1831,14 +1864,15 @@ lazy_vacuum_all_indexes(Relation onerel, Relation *Irel,
18311864 lps -> lvshared -> reltuples = vacrelstats -> old_live_tuples ;
18321865 lps -> lvshared -> estimated_count = true;
18331866
1834- lazy_parallel_vacuum_indexes (Irel , stats , vacrelstats , lps , nindexes );
1867+ lazy_parallel_vacuum_indexes (Irel , vacrelstats , lps , nindexes );
18351868 }
18361869 else
18371870 {
18381871 int idx ;
18391872
18401873 for (idx = 0 ; idx < nindexes ; idx ++ )
1841- lazy_vacuum_index (Irel [idx ], & stats [idx ], vacrelstats -> dead_tuples ,
1874+ lazy_vacuum_index (Irel [idx ], & (vacrelstats -> indstats [idx ]),
1875+ vacrelstats -> dead_tuples ,
18421876 vacrelstats -> old_live_tuples , vacrelstats );
18431877 }
18441878
@@ -2109,9 +2143,8 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats)
21092143 * cleanup.
21102144 */
21112145static void
2112- lazy_parallel_vacuum_indexes (Relation * Irel , IndexBulkDeleteResult * * stats ,
2113- LVRelStats * vacrelstats , LVParallelState * lps ,
2114- int nindexes )
2146+ lazy_parallel_vacuum_indexes (Relation * Irel , LVRelStats * vacrelstats ,
2147+ LVParallelState * lps , int nindexes )
21152148{
21162149 int nworkers ;
21172150
@@ -2199,14 +2232,14 @@ lazy_parallel_vacuum_indexes(Relation *Irel, IndexBulkDeleteResult **stats,
21992232 }
22002233
22012234 /* Process the indexes that can be processed by only leader process */
2202- vacuum_indexes_leader (Irel , stats , vacrelstats , lps , nindexes );
2235+ vacuum_indexes_leader (Irel , vacrelstats , lps , nindexes );
22032236
22042237 /*
22052238 * Join as a parallel worker. The leader process alone processes all the
22062239 * indexes in the case where no workers are launched.
22072240 */
2208- parallel_vacuum_index (Irel , stats , lps -> lvshared ,
2209- vacrelstats -> dead_tuples , nindexes , vacrelstats );
2241+ parallel_vacuum_index (Irel , lps -> lvshared , vacrelstats -> dead_tuples ,
2242+ nindexes , vacrelstats );
22102243
22112244 /*
22122245 * Next, accumulate buffer and WAL usage. (This must wait for the workers
@@ -2239,9 +2272,9 @@ lazy_parallel_vacuum_indexes(Relation *Irel, IndexBulkDeleteResult **stats,
22392272 * vacuum worker processes to process the indexes in parallel.
22402273 */
22412274static void
2242- parallel_vacuum_index (Relation * Irel , IndexBulkDeleteResult * * stats ,
2243- LVShared * lvshared , LVDeadTuples * dead_tuples ,
2244- int nindexes , LVRelStats * vacrelstats )
2275+ parallel_vacuum_index (Relation * Irel , LVShared * lvshared ,
2276+ LVDeadTuples * dead_tuples , int nindexes ,
2277+ LVRelStats * vacrelstats )
22452278{
22462279 /*
22472280 * Increment the active worker count if we are able to launch any worker.
@@ -2274,8 +2307,8 @@ parallel_vacuum_index(Relation *Irel, IndexBulkDeleteResult **stats,
22742307 continue ;
22752308
22762309 /* Do vacuum or cleanup of the index */
2277- vacuum_one_index (Irel [idx ], & (stats [idx ]), lvshared , shared_indstats ,
2278- dead_tuples , vacrelstats );
2310+ vacuum_one_index (Irel [idx ], & (vacrelstats -> indstats [idx ]), lvshared ,
2311+ shared_indstats , dead_tuples , vacrelstats );
22792312 }
22802313
22812314 /*
@@ -2291,9 +2324,8 @@ parallel_vacuum_index(Relation *Irel, IndexBulkDeleteResult **stats,
22912324 * because these indexes don't support parallel operation at that phase.
22922325 */
22932326static void
2294- vacuum_indexes_leader (Relation * Irel , IndexBulkDeleteResult * * stats ,
2295- LVRelStats * vacrelstats , LVParallelState * lps ,
2296- int nindexes )
2327+ vacuum_indexes_leader (Relation * Irel , LVRelStats * vacrelstats ,
2328+ LVParallelState * lps , int nindexes )
22972329{
22982330 int i ;
22992331
@@ -2314,7 +2346,7 @@ vacuum_indexes_leader(Relation *Irel, IndexBulkDeleteResult **stats,
23142346 /* Process the indexes skipped by parallel workers */
23152347 if (shared_indstats == NULL ||
23162348 skip_parallel_vacuum_index (Irel [i ], lps -> lvshared ))
2317- vacuum_one_index (Irel [i ], & (stats [i ]), lps -> lvshared ,
2349+ vacuum_one_index (Irel [i ], & (vacrelstats -> indstats [i ]), lps -> lvshared ,
23182350 shared_indstats , vacrelstats -> dead_tuples ,
23192351 vacrelstats );
23202352 }
@@ -2394,9 +2426,8 @@ vacuum_one_index(Relation indrel, IndexBulkDeleteResult **stats,
23942426 * parallel vacuum.
23952427 */
23962428static void
2397- lazy_cleanup_all_indexes (Relation * Irel , IndexBulkDeleteResult * * stats ,
2398- LVRelStats * vacrelstats , LVParallelState * lps ,
2399- int nindexes )
2429+ lazy_cleanup_all_indexes (Relation * Irel , LVRelStats * vacrelstats ,
2430+ LVParallelState * lps , int nindexes )
24002431{
24012432 int idx ;
24022433
@@ -2427,12 +2458,12 @@ lazy_cleanup_all_indexes(Relation *Irel, IndexBulkDeleteResult **stats,
24272458 lps -> lvshared -> estimated_count =
24282459 (vacrelstats -> tupcount_pages < vacrelstats -> rel_pages );
24292460
2430- lazy_parallel_vacuum_indexes (Irel , stats , vacrelstats , lps , nindexes );
2461+ lazy_parallel_vacuum_indexes (Irel , vacrelstats , lps , nindexes );
24312462 }
24322463 else
24332464 {
24342465 for (idx = 0 ; idx < nindexes ; idx ++ )
2435- lazy_cleanup_index (Irel [idx ], & stats [idx ],
2466+ lazy_cleanup_index (Irel [idx ], & ( vacrelstats -> indstats [idx ]) ,
24362467 vacrelstats -> new_rel_tuples ,
24372468 vacrelstats -> tupcount_pages < vacrelstats -> rel_pages ,
24382469 vacrelstats );
@@ -3243,7 +3274,6 @@ update_index_statistics(Relation *Irel, IndexBulkDeleteResult **stats,
32433274 InvalidTransactionId ,
32443275 InvalidMultiXactId ,
32453276 false);
3246- pfree (stats [i ]);
32473277 }
32483278}
32493279
@@ -3550,7 +3580,6 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
35503580 WalUsage * wal_usage ;
35513581 int nindexes ;
35523582 char * sharedquery ;
3553- IndexBulkDeleteResult * * stats ;
35543583 LVRelStats vacrelstats ;
35553584 ErrorContextCallback errcallback ;
35563585
@@ -3597,7 +3626,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
35973626 VacuumSharedCostBalance = & (lvshared -> cost_balance );
35983627 VacuumActiveNWorkers = & (lvshared -> active_nworkers );
35993628
3600- stats = (IndexBulkDeleteResult * * )
3629+ vacrelstats . indstats = (IndexBulkDeleteResult * * )
36013630 palloc0 (nindexes * sizeof (IndexBulkDeleteResult * ));
36023631
36033632 if (lvshared -> maintenance_work_mem_worker > 0 )
@@ -3622,7 +3651,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
36223651 InstrStartParallelQuery ();
36233652
36243653 /* Process indexes to perform vacuum/cleanup */
3625- parallel_vacuum_index (indrels , stats , lvshared , dead_tuples , nindexes ,
3654+ parallel_vacuum_index (indrels , lvshared , dead_tuples , nindexes ,
36263655 & vacrelstats );
36273656
36283657 /* Report buffer/WAL usage during parallel execution */
@@ -3636,7 +3665,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
36363665
36373666 vac_close_indexes (nindexes , indrels , RowExclusiveLock );
36383667 table_close (onerel , ShareUpdateExclusiveLock );
3639- pfree (stats );
3668+ pfree (vacrelstats . indstats );
36403669}
36413670
36423671/*
0 commit comments