@@ -115,7 +115,8 @@ typedef enum pgssVersion
115
115
{
116
116
PGSS_V1_0 = 0 ,
117
117
PGSS_V1_1 ,
118
- PGSS_V1_2
118
+ PGSS_V1_2 ,
119
+ PGSS_V1_3
119
120
} pgssVersion ;
120
121
121
122
/*
@@ -136,6 +137,10 @@ typedef struct Counters
136
137
{
137
138
int64 calls ; /* # of times executed */
138
139
double total_time ; /* total execution time, in msec */
140
+ double min_time ; /* minimim execution time in msec */
141
+ double max_time ; /* maximum execution time in msec */
142
+ double mean_time ; /* mean execution time in msec */
143
+ double sum_var_time ; /* sum of variances in execution time in msec */
139
144
int64 rows ; /* total # of retrieved or affected rows */
140
145
int64 shared_blks_hit ; /* # of shared buffer hits */
141
146
int64 shared_blks_read ; /* # of shared disk blocks read */
@@ -274,6 +279,7 @@ void _PG_fini(void);
274
279
275
280
PG_FUNCTION_INFO_V1 (pg_stat_statements_reset );
276
281
PG_FUNCTION_INFO_V1 (pg_stat_statements_1_2 );
282
+ PG_FUNCTION_INFO_V1 (pg_stat_statements_1_3 );
277
283
PG_FUNCTION_INFO_V1 (pg_stat_statements );
278
284
279
285
static void pgss_shmem_startup (void );
@@ -320,6 +326,7 @@ static char *generate_normalized_query(pgssJumbleState *jstate, const char *quer
320
326
int * query_len_p , int encoding );
321
327
static void fill_in_constant_lengths (pgssJumbleState * jstate , const char * query );
322
328
static int comp_location (const void * a , const void * b );
329
+ static inline double sqrtd (const double x );
323
330
324
331
325
332
/*
@@ -1215,6 +1222,32 @@ pgss_store(const char *query, uint32 queryId,
1215
1222
1216
1223
e -> counters .calls += 1 ;
1217
1224
e -> counters .total_time += total_time ;
1225
+ if (e -> counters .calls == 1 )
1226
+ {
1227
+ e -> counters .min_time = total_time ;
1228
+ e -> counters .max_time = total_time ;
1229
+ e -> counters .mean_time = total_time ;
1230
+ }
1231
+ else
1232
+ {
1233
+ /*
1234
+ * Welford's method for accurately computing variance.
1235
+ * See <http://www.johndcook.com/blog/standard_deviation/>
1236
+ */
1237
+ double old_mean = e -> counters .mean_time ;
1238
+
1239
+ e -> counters .mean_time +=
1240
+ (total_time - old_mean ) / e -> counters .calls ;
1241
+ e -> counters .sum_var_time +=
1242
+ (total_time - old_mean ) * (total_time - e -> counters .mean_time );
1243
+
1244
+ /* calculate min and max time */
1245
+ if (e -> counters .min_time > total_time )
1246
+ e -> counters .min_time = total_time ;
1247
+ if (e -> counters .max_time < total_time )
1248
+ e -> counters .max_time = total_time ;
1249
+
1250
+ }
1218
1251
e -> counters .rows += rows ;
1219
1252
e -> counters .shared_blks_hit += bufusage -> shared_blks_hit ;
1220
1253
e -> counters .shared_blks_read += bufusage -> shared_blks_read ;
@@ -1259,7 +1292,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
1259
1292
#define PG_STAT_STATEMENTS_COLS_V1_0 14
1260
1293
#define PG_STAT_STATEMENTS_COLS_V1_1 18
1261
1294
#define PG_STAT_STATEMENTS_COLS_V1_2 19
1262
- #define PG_STAT_STATEMENTS_COLS 19 /* maximum of above */
1295
+ #define PG_STAT_STATEMENTS_COLS_V1_3 23
1296
+ #define PG_STAT_STATEMENTS_COLS 23 /* maximum of above */
1263
1297
1264
1298
/*
1265
1299
* Retrieve statement statistics.
@@ -1271,6 +1305,16 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
1271
1305
* expected API version is identified by embedding it in the C name of the
1272
1306
* function. Unfortunately we weren't bright enough to do that for 1.1.
1273
1307
*/
1308
+ Datum
1309
+ pg_stat_statements_1_3 (PG_FUNCTION_ARGS )
1310
+ {
1311
+ bool showtext = PG_GETARG_BOOL (0 );
1312
+
1313
+ pg_stat_statements_internal (fcinfo , PGSS_V1_3 , showtext );
1314
+
1315
+ return (Datum ) 0 ;
1316
+ }
1317
+
1274
1318
Datum
1275
1319
pg_stat_statements_1_2 (PG_FUNCTION_ARGS )
1276
1320
{
@@ -1360,6 +1404,10 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
1360
1404
if (api_version != PGSS_V1_2 )
1361
1405
elog (ERROR , "incorrect number of output arguments" );
1362
1406
break ;
1407
+ case PG_STAT_STATEMENTS_COLS_V1_3 :
1408
+ if (api_version != PGSS_V1_3 )
1409
+ elog (ERROR , "incorrect number of output arguments" );
1410
+ break ;
1363
1411
default :
1364
1412
elog (ERROR , "incorrect number of output arguments" );
1365
1413
}
@@ -1519,6 +1567,23 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
1519
1567
1520
1568
values [i ++ ] = Int64GetDatumFast (tmp .calls );
1521
1569
values [i ++ ] = Float8GetDatumFast (tmp .total_time );
1570
+ if (api_version >= PGSS_V1_3 )
1571
+ {
1572
+ values [i ++ ] = Float8GetDatumFast (tmp .min_time );
1573
+ values [i ++ ] = Float8GetDatumFast (tmp .max_time );
1574
+ values [i ++ ] = Float8GetDatumFast (tmp .mean_time );
1575
+ /*
1576
+ * Note we are calculating the population variance here, not the
1577
+ * sample variance, as we have data for the whole population,
1578
+ * so Bessel's correction is not used, and we don't divide by
1579
+ * tmp.calls - 1.
1580
+ */
1581
+ if (tmp .calls > 1 )
1582
+ values [i ++ ] =
1583
+ Float8GetDatumFast (sqrtd (tmp .sum_var_time / tmp .calls ));
1584
+ else
1585
+ values [i ++ ] = Float8GetDatumFast (0.0 );
1586
+ }
1522
1587
values [i ++ ] = Int64GetDatumFast (tmp .rows );
1523
1588
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_hit );
1524
1589
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_read );
@@ -1541,6 +1606,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
1541
1606
Assert (i == (api_version == PGSS_V1_0 ? PG_STAT_STATEMENTS_COLS_V1_0 :
1542
1607
api_version == PGSS_V1_1 ? PG_STAT_STATEMENTS_COLS_V1_1 :
1543
1608
api_version == PGSS_V1_2 ? PG_STAT_STATEMENTS_COLS_V1_2 :
1609
+ api_version == PGSS_V1_3 ? PG_STAT_STATEMENTS_COLS_V1_3 :
1544
1610
-1 /* fail if you forget to update this assert */ ));
1545
1611
1546
1612
tuplestore_putvalues (tupstore , tupdesc , values , nulls );
@@ -2899,3 +2965,20 @@ comp_location(const void *a, const void *b)
2899
2965
else
2900
2966
return 0 ;
2901
2967
}
2968
+
2969
+ /*
2970
+ * fast sqrt algorithm: reference from Fast inverse square root algorithms.
2971
+ */
2972
+ static inline double
2973
+ sqrtd (const double x )
2974
+ {
2975
+ double x_half = 0.5 * x ;
2976
+ long long int tmp = 0x5FE6EB50C7B537AAl - ( * (long long int * )& x >> 1 );
2977
+ double x_result = * (double * )& tmp ;
2978
+
2979
+ x_result *= (1.5 - (x_half * x_result * x_result ));
2980
+ /* If retry this calculation, it becomes higher precision at sqrt */
2981
+ x_result *= (1.5 - (x_half * x_result * x_result ));
2982
+
2983
+ return x_result * x ;
2984
+ }
0 commit comments