@@ -312,6 +312,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
312
312
Oid save_userid ;
313
313
int save_sec_context ;
314
314
int save_nestlevel ;
315
+ int64 AnalyzePageHit = VacuumPageHit ;
316
+ int64 AnalyzePageMiss = VacuumPageMiss ;
317
+ int64 AnalyzePageDirty = VacuumPageDirty ;
318
+ PgStat_Counter startreadtime = 0 ;
319
+ PgStat_Counter startwritetime = 0 ;
315
320
316
321
if (inh )
317
322
ereport (elevel ,
@@ -346,8 +351,14 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
346
351
/* measure elapsed time iff autovacuum logging requires it */
347
352
if (IsAutoVacuumWorkerProcess () && params -> log_min_duration >= 0 )
348
353
{
354
+ if (track_io_timing )
355
+ {
356
+ startreadtime = pgStatBlockReadTime ;
357
+ startwritetime = pgStatBlockWriteTime ;
358
+ }
359
+
349
360
pg_rusage_init (& ru0 );
350
- if (params -> log_min_duration > 0 )
361
+ if (params -> log_min_duration >= 0 )
351
362
starttime = GetCurrentTimestamp ();
352
363
}
353
364
@@ -692,15 +703,90 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
692
703
/* Log the action if appropriate */
693
704
if (IsAutoVacuumWorkerProcess () && params -> log_min_duration >= 0 )
694
705
{
706
+ TimestampTz endtime = GetCurrentTimestamp ();
707
+
695
708
if (params -> log_min_duration == 0 ||
696
- TimestampDifferenceExceeds (starttime , GetCurrentTimestamp () ,
709
+ TimestampDifferenceExceeds (starttime , endtime ,
697
710
params -> log_min_duration ))
711
+ {
712
+ long delay_in_ms ;
713
+ double read_rate = 0 ;
714
+ double write_rate = 0 ;
715
+ StringInfoData buf ;
716
+
717
+ /*
718
+ * Calculate the difference in the Page Hit/Miss/Dirty that
719
+ * happened as part of the analyze by subtracting out the
720
+ * pre-analyze values which we saved above.
721
+ */
722
+ AnalyzePageHit = VacuumPageHit - AnalyzePageHit ;
723
+ AnalyzePageMiss = VacuumPageMiss - AnalyzePageMiss ;
724
+ AnalyzePageDirty = VacuumPageDirty - AnalyzePageDirty ;
725
+
726
+ /*
727
+ * We do not expect an analyze to take > 25 days and it simplifies
728
+ * things a bit to use TimestampDifferenceMilliseconds.
729
+ */
730
+ delay_in_ms = TimestampDifferenceMilliseconds (starttime , endtime );
731
+
732
+ /*
733
+ * Note that we are reporting these read/write rates in the same
734
+ * manner as VACUUM does, which means that while the 'average read
735
+ * rate' here actually corresponds to page misses and resulting
736
+ * reads which are also picked up by track_io_timing, if enabled,
737
+ * the 'average write rate' is actually talking about the rate of
738
+ * pages being dirtied, not being written out, so it's typical to
739
+ * have a non-zero 'avg write rate' while I/O Timings only reports
740
+ * reads.
741
+ *
742
+ * It's not clear that an ANALYZE will ever result in
743
+ * FlushBuffer() being called, but we track and support reporting
744
+ * on I/O write time in case that changes as it's practically free
745
+ * to do so anyway.
746
+ */
747
+
748
+ if (delay_in_ms > 0 )
749
+ {
750
+ read_rate = (double ) BLCKSZ * AnalyzePageMiss / (1024 * 1024 ) /
751
+ (delay_in_ms / 1000.0 );
752
+ write_rate = (double ) BLCKSZ * AnalyzePageDirty / (1024 * 1024 ) /
753
+ (delay_in_ms / 1000.0 );
754
+ }
755
+
756
+ /*
757
+ * We split this up so we don't emit empty I/O timing values when
758
+ * track_io_timing isn't enabled.
759
+ */
760
+
761
+ initStringInfo (& buf );
762
+ appendStringInfo (& buf , _ ("automatic analyze of table \"%s.%s.%s\"\n" ),
763
+ get_database_name (MyDatabaseId ),
764
+ get_namespace_name (RelationGetNamespace (onerel )),
765
+ RelationGetRelationName (onerel ));
766
+ appendStringInfo (& buf , _ ("buffer usage: %lld hits, %lld misses, %lld dirtied\n" ),
767
+ (long long ) AnalyzePageHit ,
768
+ (long long ) AnalyzePageMiss ,
769
+ (long long ) AnalyzePageDirty );
770
+ appendStringInfo (& buf , _ ("avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" ),
771
+ read_rate , write_rate );
772
+ if (track_io_timing )
773
+ {
774
+ appendStringInfoString (& buf , _ ("I/O Timings:" ));
775
+ if (pgStatBlockReadTime - startreadtime > 0 )
776
+ appendStringInfo (& buf , _ (" read=%.3f" ),
777
+ (double ) (pgStatBlockReadTime - startreadtime ) / 1000 );
778
+ if (pgStatBlockWriteTime - startwritetime > 0 )
779
+ appendStringInfo (& buf , _ (" write=%.3f" ),
780
+ (double ) (pgStatBlockWriteTime - startwritetime ) / 1000 );
781
+ appendStringInfoChar (& buf , '\n' );
782
+ }
783
+ appendStringInfo (& buf , _ ("system usage: %s" ), pg_rusage_show (& ru0 ));
784
+
698
785
ereport (LOG ,
699
- (errmsg ("automatic analyze of table \"%s.%s.%s\" system usage: %s" ,
700
- get_database_name (MyDatabaseId ),
701
- get_namespace_name (RelationGetNamespace (onerel )),
702
- RelationGetRelationName (onerel ),
703
- pg_rusage_show (& ru0 ))));
786
+ (errmsg_internal ("%s" , buf .data )));
787
+
788
+ pfree (buf .data );
789
+ }
704
790
}
705
791
706
792
/* Roll back any GUC changes executed by index functions */
0 commit comments