@@ -188,6 +188,9 @@ typedef struct Counters
188
188
double blk_read_time ; /* time spent reading, in msec */
189
189
double blk_write_time ; /* time spent writing, in msec */
190
190
double usage ; /* usage factor */
191
+ int64 wal_records ; /* # of WAL records generated */
192
+ int64 wal_num_fpw ; /* # of WAL full page image records generated */
193
+ uint64 wal_bytes ; /* total amount of WAL bytes generated */
191
194
} Counters ;
192
195
193
196
/*
@@ -348,6 +351,7 @@ static void pgss_store(const char *query, uint64 queryId,
348
351
pgssStoreKind kind ,
349
352
double total_time , uint64 rows ,
350
353
const BufferUsage * bufusage ,
354
+ const WalUsage * walusage ,
351
355
pgssJumbleState * jstate );
352
356
static void pg_stat_statements_internal (FunctionCallInfo fcinfo ,
353
357
pgssVersion api_version ,
@@ -891,6 +895,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
891
895
0 ,
892
896
0 ,
893
897
NULL ,
898
+ NULL ,
894
899
& jstate );
895
900
}
896
901
@@ -926,9 +931,17 @@ pgss_planner(Query *parse,
926
931
instr_time duration ;
927
932
BufferUsage bufusage_start ,
928
933
bufusage ;
934
+ WalUsage walusage_start ,
935
+ walusage ;
929
936
930
937
/* We need to track buffer usage as the planner can access them. */
931
938
bufusage_start = pgBufferUsage ;
939
+
940
+ /*
941
+ * Similarly the planner could write some WAL records in some cases
942
+ * (e.g. setting a hint bit with those being WAL-logged)
943
+ */
944
+ walusage_start = pgWalUsage ;
932
945
INSTR_TIME_SET_CURRENT (start );
933
946
934
947
plan_nested_level ++ ;
@@ -954,6 +967,10 @@ pgss_planner(Query *parse,
954
967
memset (& bufusage , 0 , sizeof (BufferUsage ));
955
968
BufferUsageAccumDiff (& bufusage , & pgBufferUsage , & bufusage_start );
956
969
970
+ /* calc differences of WAL counters. */
971
+ memset (& walusage , 0 , sizeof (WalUsage ));
972
+ WalUsageAccumDiff (& walusage , & pgWalUsage , & walusage_start );
973
+
957
974
pgss_store (query_string ,
958
975
parse -> queryId ,
959
976
parse -> stmt_location ,
@@ -962,6 +979,7 @@ pgss_planner(Query *parse,
962
979
INSTR_TIME_GET_MILLISEC (duration ),
963
980
0 ,
964
981
& bufusage ,
982
+ & walusage ,
965
983
NULL );
966
984
}
967
985
else
@@ -1079,6 +1097,7 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
1079
1097
queryDesc -> totaltime -> total * 1000.0 , /* convert to msec */
1080
1098
queryDesc -> estate -> es_processed ,
1081
1099
& queryDesc -> totaltime -> bufusage ,
1100
+ & queryDesc -> totaltime -> walusage ,
1082
1101
NULL );
1083
1102
}
1084
1103
@@ -1123,8 +1142,11 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
1123
1142
uint64 rows ;
1124
1143
BufferUsage bufusage_start ,
1125
1144
bufusage ;
1145
+ WalUsage walusage_start ,
1146
+ walusage ;
1126
1147
1127
1148
bufusage_start = pgBufferUsage ;
1149
+ walusage_start = pgWalUsage ;
1128
1150
INSTR_TIME_SET_CURRENT (start );
1129
1151
1130
1152
exec_nested_level ++ ;
@@ -1154,6 +1176,10 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
1154
1176
memset (& bufusage , 0 , sizeof (BufferUsage ));
1155
1177
BufferUsageAccumDiff (& bufusage , & pgBufferUsage , & bufusage_start );
1156
1178
1179
+ /* calc differences of WAL counters. */
1180
+ memset (& walusage , 0 , sizeof (WalUsage ));
1181
+ WalUsageAccumDiff (& walusage , & pgWalUsage , & walusage_start );
1182
+
1157
1183
pgss_store (queryString ,
1158
1184
0 , /* signal that it's a utility stmt */
1159
1185
pstmt -> stmt_location ,
@@ -1162,6 +1188,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
1162
1188
INSTR_TIME_GET_MILLISEC (duration ),
1163
1189
rows ,
1164
1190
& bufusage ,
1191
+ & walusage ,
1165
1192
NULL );
1166
1193
}
1167
1194
else
@@ -1197,7 +1224,8 @@ pgss_hash_string(const char *str, int len)
1197
1224
*
1198
1225
* If jstate is not NULL then we're trying to create an entry for which
1199
1226
* we have no statistics as yet; we just want to record the normalized
1200
- * query string. total_time, rows, bufusage are ignored in this case.
1227
+ * query string. total_time, rows, bufusage and walusage are ignored in this
1228
+ * case.
1201
1229
*
1202
1230
* If kind is PGSS_PLAN or PGSS_EXEC, its value is used as the array position
1203
1231
* for the arrays in the Counters field.
@@ -1208,6 +1236,7 @@ pgss_store(const char *query, uint64 queryId,
1208
1236
pgssStoreKind kind ,
1209
1237
double total_time , uint64 rows ,
1210
1238
const BufferUsage * bufusage ,
1239
+ const WalUsage * walusage ,
1211
1240
pgssJumbleState * jstate )
1212
1241
{
1213
1242
pgssHashKey key ;
@@ -1402,6 +1431,9 @@ pgss_store(const char *query, uint64 queryId,
1402
1431
e -> counters .blk_read_time += INSTR_TIME_GET_MILLISEC (bufusage -> blk_read_time );
1403
1432
e -> counters .blk_write_time += INSTR_TIME_GET_MILLISEC (bufusage -> blk_write_time );
1404
1433
e -> counters .usage += USAGE_EXEC (total_time );
1434
+ e -> counters .wal_records += walusage -> wal_records ;
1435
+ e -> counters .wal_num_fpw += walusage -> wal_num_fpw ;
1436
+ e -> counters .wal_bytes += walusage -> wal_bytes ;
1405
1437
1406
1438
SpinLockRelease (& e -> mutex );
1407
1439
}
@@ -1449,8 +1481,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
1449
1481
#define PG_STAT_STATEMENTS_COLS_V1_1 18
1450
1482
#define PG_STAT_STATEMENTS_COLS_V1_2 19
1451
1483
#define PG_STAT_STATEMENTS_COLS_V1_3 23
1452
- #define PG_STAT_STATEMENTS_COLS_V1_8 29
1453
- #define PG_STAT_STATEMENTS_COLS 29 /* maximum of above */
1484
+ #define PG_STAT_STATEMENTS_COLS_V1_8 32
1485
+ #define PG_STAT_STATEMENTS_COLS 32 /* maximum of above */
1454
1486
1455
1487
/*
1456
1488
* Retrieve statement statistics.
@@ -1786,6 +1818,23 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
1786
1818
values [i ++ ] = Float8GetDatumFast (tmp .blk_read_time );
1787
1819
values [i ++ ] = Float8GetDatumFast (tmp .blk_write_time );
1788
1820
}
1821
+ if (api_version >= PGSS_V1_8 )
1822
+ {
1823
+ char buf [256 ];
1824
+ Datum wal_bytes ;
1825
+
1826
+ values [i ++ ] = Int64GetDatumFast (tmp .wal_records );
1827
+ values [i ++ ] = Int64GetDatumFast (tmp .wal_num_fpw );
1828
+
1829
+ snprintf (buf , sizeof buf , UINT64_FORMAT , tmp .wal_bytes );
1830
+
1831
+ /* Convert to numeric. */
1832
+ wal_bytes = DirectFunctionCall3 (numeric_in ,
1833
+ CStringGetDatum (buf ),
1834
+ ObjectIdGetDatum (0 ),
1835
+ Int32GetDatum (-1 ));
1836
+ values [i ++ ] = wal_bytes ;
1837
+ }
1789
1838
1790
1839
Assert (i == (api_version == PGSS_V1_0 ? PG_STAT_STATEMENTS_COLS_V1_0 :
1791
1840
api_version == PGSS_V1_1 ? PG_STAT_STATEMENTS_COLS_V1_1 :
0 commit comments