@@ -517,6 +517,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
517517 bool aggressive ; /* should we scan all unfrozen pages? */
518518 bool scanned_all_unfrozen ; /* actually scanned all such pages? */
519519 bool freeze_age_vacuum ; /* aggressive due to freeze age? */
520+ instr_time vacstart ;
521+ int64 startdelaytime ;
522+ instr_time vacend ;
520523 char * * indnames = NULL ;
521524 TransactionId xidFullScanLimit ;
522525 MultiXactId mxactFullScanLimit ;
@@ -535,6 +538,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
535538 /* Used for instrumentation and cumulative maintenance statistics. */
536539 starttime = GetCurrentTimestamp ();
537540
541+ /* measure elapsed and delay time for the vacuum statistics */
542+ INSTR_TIME_SET_CURRENT (vacstart );
543+ startdelaytime = VacuumDelayTime ;
544+
538545 /* measure elapsed time iff autovacuum logging requires it */
539546 if (IsAutoVacuumWorkerProcess () && params -> log_min_duration >= 0 )
540547 {
@@ -767,11 +774,13 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
767774 pgstat_report_vacuum (RelationGetRelid (rel ),
768775 rel -> rd_rel -> relisshared ,
769776 Max (new_live_tuples , 0 ),
770- vacrel -> new_dead_tuples , starttime );
777+ vacrel -> new_dead_tuples , starttime ,
778+ VacuumDelayTime - startdelaytime );
771779
772780 /* assemble the per-vacuum measurements for subsequent reporting */
773781 {
774782 PgStat_VacuumStats vacstats ;
783+ PgStat_Counter elapsedtime ;
775784
776785 MemSet (& vacstats , 0 , sizeof (vacstats ));
777786 vacstats .tuples_deleted = (PgStat_Counter ) vacrel -> tuples_deleted ;
@@ -782,9 +791,16 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
782791 vacstats .pages_all_visible = (PgStat_Counter ) vacrel -> pages_all_visible ;
783792 vacstats .freeze_age_vacuum_count = freeze_age_vacuum ? 1 : 0 ;
784793
794+ INSTR_TIME_SET_CURRENT (vacend );
795+ INSTR_TIME_SUBTRACT (vacend , vacstart );
796+ elapsedtime = (PgStat_Counter ) INSTR_TIME_GET_MICROSEC (vacend );
797+
785798 ereport (elevel ,
786799 (errmsg ("table \"%s\": vacuum statistics" , vacrel -> relname ),
787- errdetail ("aggressive scan required by freeze age: %s" ,
800+ errdetail ("elapsed: %.3f ms, cost-based delay: %.3f ms\n"
801+ "aggressive scan required by freeze age: %s" ,
802+ elapsedtime / 1000.0 ,
803+ (VacuumDelayTime - startdelaytime ) / 1000.0 ,
788804 freeze_age_vacuum ? _ ("yes" ) : _ ("no" ))));
789805
790806 }
@@ -930,6 +946,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
930946 (long long ) walusage .wal_records ,
931947 (long long ) walusage .wal_fpi ,
932948 (unsigned long long ) walusage .wal_bytes );
949+ appendStringInfo (& buf , _ ("cost-based delay: %.3f ms\n" ),
950+ (VacuumDelayTime - startdelaytime ) / 1000.0 );
933951 appendStringInfo (& buf , _ ("system usage: %s" ), pg_rusage_show (& ru0 ));
934952
935953 ereport (LOG ,
@@ -3117,7 +3135,8 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
31173135 * is skipped, and keeps it from being counted twice when it is not.
31183136 */
31193137static IndexBulkDeleteResult
3120- lazy_index_vacstats_start (IndexBulkDeleteResult * istat )
3138+ lazy_index_vacstats_start (IndexBulkDeleteResult * istat ,
3139+ instr_time * starttime , int64 * startdelaytime )
31213140{
31223141 IndexBulkDeleteResult before ;
31233142
@@ -3126,6 +3145,9 @@ lazy_index_vacstats_start(IndexBulkDeleteResult *istat)
31263145 else
31273146 MemSet (& before , 0 , sizeof (before ));
31283147
3148+ INSTR_TIME_SET_CURRENT (* starttime );
3149+ * startdelaytime = VacuumDelayTime ;
3150+
31293151 return before ;
31303152}
31313153
@@ -3139,9 +3161,14 @@ lazy_index_vacstats_start(IndexBulkDeleteResult *istat)
31393161 */
31403162static void
31413163lazy_index_vacstats_finish (Relation indrel , IndexBulkDeleteResult * istat ,
3142- IndexBulkDeleteResult * before , bool cleanup )
3164+ IndexBulkDeleteResult * before , bool cleanup ,
3165+ instr_time starttime , int64 startdelaytime )
31433166{
31443167 PgStat_VacuumStats vacstats ;
3168+ instr_time endtime ;
3169+
3170+ INSTR_TIME_SET_CURRENT (endtime );
3171+ INSTR_TIME_SUBTRACT (endtime , starttime );
31453172
31463173 MemSet (& vacstats , 0 , sizeof (vacstats ));
31473174 if (istat )
@@ -3162,6 +3189,11 @@ lazy_index_vacstats_finish(Relation indrel, IndexBulkDeleteResult *istat,
31623189 (PgStat_Counter ) (istat -> pages_deleted - istat -> pages_free );
31633190 }
31643191
3192+ pgstat_report_index_vacuum_time (indrel ,
3193+ (PgStat_Counter ) INSTR_TIME_GET_MICROSEC (endtime ),
3194+ VacuumDelayTime - startdelaytime ,
3195+ IsAutoVacuumWorkerProcess ());
3196+
31653197}
31663198
31673199/*
@@ -3183,6 +3215,8 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
31833215 PGRUsage ru0 ;
31843216 LVSavedErrInfo saved_err_info ;
31853217 IndexBulkDeleteResult istat_before ;
3218+ instr_time starttime ;
3219+ int64 startdelaytime ;
31863220
31873221 pg_rusage_init (& ru0 );
31883222
@@ -3207,15 +3241,19 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat,
32073241 InvalidBlockNumber , InvalidOffsetNumber );
32083242
32093243 /* Do bulk deletion */
3210- istat_before = lazy_index_vacstats_start (istat );
3244+ istat_before = lazy_index_vacstats_start (istat , & starttime ,
3245+ & startdelaytime );
32113246 istat = index_bulk_delete (& ivinfo , istat , lazy_tid_reaped ,
32123247 (void * ) vacrel -> dead_tuples );
3213- lazy_index_vacstats_finish (indrel , istat , & istat_before , false);
3248+ lazy_index_vacstats_finish (indrel , istat , & istat_before , false,
3249+ starttime , startdelaytime );
32143250
32153251 ereport (elevel ,
32163252 (errmsg ("scanned index \"%s\" to remove %d row versions" ,
32173253 vacrel -> indname , vacrel -> dead_tuples -> num_tuples ),
3218- errdetail_internal ("%s" , pg_rusage_show (& ru0 ))));
3254+ errdetail ("cost-based delay: %.3f ms\n%s" ,
3255+ (VacuumDelayTime - startdelaytime ) / 1000.0 ,
3256+ pg_rusage_show (& ru0 ))));
32193257
32203258 /* Revert to the previous phase information for error traceback */
32213259 restore_vacuum_error_info (vacrel , & saved_err_info );
@@ -3242,6 +3280,8 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
32423280 PGRUsage ru0 ;
32433281 LVSavedErrInfo saved_err_info ;
32443282 IndexBulkDeleteResult istat_before ;
3283+ instr_time starttime ;
3284+ int64 startdelaytime ;
32453285
32463286 pg_rusage_init (& ru0 );
32473287
@@ -3266,9 +3306,11 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
32663306 VACUUM_ERRCB_PHASE_INDEX_CLEANUP ,
32673307 InvalidBlockNumber , InvalidOffsetNumber );
32683308
3269- istat_before = lazy_index_vacstats_start (istat );
3309+ istat_before = lazy_index_vacstats_start (istat , & starttime ,
3310+ & startdelaytime );
32703311 istat = index_vacuum_cleanup (& ivinfo , istat );
3271- lazy_index_vacstats_finish (indrel , istat , & istat_before , true);
3312+ lazy_index_vacstats_finish (indrel , istat , & istat_before , true,
3313+ starttime , startdelaytime );
32723314
32733315 if (istat )
32743316 {
@@ -3280,10 +3322,12 @@ lazy_cleanup_one_index(Relation indrel, IndexBulkDeleteResult *istat,
32803322 errdetail ("%.0f index row versions were removed.\n"
32813323 "%u index pages were newly deleted.\n"
32823324 "%u index pages are currently deleted, of which %u are currently reusable.\n"
3325+ "cost-based delay: %.3f ms\n"
32833326 "%s." ,
32843327 (istat )-> tuples_removed ,
32853328 (istat )-> pages_newly_deleted ,
32863329 (istat )-> pages_deleted , (istat )-> pages_free ,
3330+ (VacuumDelayTime - startdelaytime ) / 1000.0 ,
32873331 pg_rusage_show (& ru0 ))));
32883332 }
32893333
0 commit comments