pg_stat_statements: Track time at which all statistics were last reset.
authorFujii Masao
Fri, 18 Dec 2020 01:49:58 +0000 (10:49 +0900)
committerFujii Masao
Fri, 18 Dec 2020 01:49:58 +0000 (10:49 +0900)
This commit adds "stats_reset" column into the pg_stat_statements_info
view. This column indicates the time at which all statistics in the
pg_stat_statements view were last reset.

Per discussion, this commit also changes pg_stat_statements_info code
so that "dealloc" column is reset at the same time as "stats_reset" is reset,
i.e., whenever all pg_stat_statements entries are removed, for the sake
of consistency. Previously "dealloc" was reset only when
pg_stat_statements_reset(0, 0, 0) is called and was not reset when
pg_stat_statements_reset() with non-zero value argument discards all
entries. This was confusing.

Author: Naoki Nakamichi, Yuki Seino
Reviewed-by: Yuki Seino, Kyotaro Horiguchi, Li Japin, Fujii Masao
Discussion: https://postgr.es/m/c102cf3180d0ee73c1c5a0f7f8558322@oss.nttdata.com

contrib/pg_stat_statements/pg_stat_statements--1.8--1.9.sql
contrib/pg_stat_statements/pg_stat_statements.c
doc/src/sgml/pgstatstatements.sgml

index 2019a4ffe034788d6d112bfe170db1418b5216d4..3504ca7eb13fd05a1392a88fd16b8562b5210c32 100644 (file)
@@ -5,9 +5,10 @@
 
 --- Define pg_stat_statements_info
 CREATE FUNCTION pg_stat_statements_info(
-    OUT dealloc bigint
+    OUT dealloc bigint,
+    OUT stats_reset timestamp with time zone
 )
-RETURNS bigint
+RETURNS record
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
 
index 2f00344b7f81ae087d76fbd285c845f92bec42e0..00eeaf10576188bd8f2f5a8fc7cb1685dbbe96a9 100644 (file)
@@ -81,6 +81,7 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
+#include "utils/timestamp.h"
 
 PG_MODULE_MAGIC;
 
@@ -98,7 +99,7 @@ PG_MODULE_MAGIC;
 #define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat"
 
 /* Magic number identifying the stats file format */
-static const uint32 PGSS_FILE_HEADER = 0x20201126;
+static const uint32 PGSS_FILE_HEADER = 0x20201218;
 
 /* PostgreSQL major version number, changes in which invalidate all entries */
 static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
@@ -199,6 +200,7 @@ typedef struct Counters
 typedef struct pgssGlobalStats
 {
    int64       dealloc;        /* # of times entries were deallocated */
+   TimestampTz stats_reset;    /* timestamp with all stats reset */
 } pgssGlobalStats;
 
 /*
@@ -565,6 +567,7 @@ pgss_shmem_startup(void)
        pgss->n_writers = 0;
        pgss->gc_count = 0;
        pgss->stats.dealloc = 0;
+       pgss->stats.stats_reset = GetCurrentTimestamp();
    }
 
    info.keysize = sizeof(pgssHashKey);
@@ -1881,6 +1884,9 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
    tuplestore_donestoring(tupstore);
 }
 
+/* Number of output arguments (columns) for pg_stat_statements_info */
+#define PG_STAT_STATEMENTS_INFO_COLS   2
+
 /*
  * Return statistics of pg_stat_statements.
  */
@@ -1888,6 +1894,16 @@ Datum
 pg_stat_statements_info(PG_FUNCTION_ARGS)
 {
    pgssGlobalStats stats;
+   TupleDesc   tupdesc;
+   Datum       values[PG_STAT_STATEMENTS_INFO_COLS];
+   bool        nulls[PG_STAT_STATEMENTS_INFO_COLS];
+
+   /* Build a tuple descriptor for our result type */
+   if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+       elog(ERROR, "return type must be a row type");
+
+   MemSet(values, 0, sizeof(values));
+   MemSet(nulls, 0, sizeof(nulls));
 
    /* Read global statistics for pg_stat_statements */
    {
@@ -1898,7 +1914,10 @@ pg_stat_statements_info(PG_FUNCTION_ARGS)
        SpinLockRelease(&s->mutex);
    }
 
-   PG_RETURN_INT64(stats.dealloc);
+   values[0] = Int64GetDatum(stats.dealloc);
+   values[1] = TimestampTzGetDatum(stats.stats_reset);
+
+   PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
 }
 
 /*
@@ -2551,21 +2570,26 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid)
            hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
            num_remove++;
        }
-
-       /* Reset global statistics for pg_stat_statements */
-       {
-           volatile pgssSharedState *s = (volatile pgssSharedState *) pgss;
-
-           SpinLockAcquire(&s->mutex);
-           s->stats.dealloc = 0;
-           SpinLockRelease(&s->mutex);
-       }
    }
 
    /* All entries are removed? */
    if (num_entries != num_remove)
        goto release_lock;
 
+   /*
+    * Reset global statistics for pg_stat_statements since all entries are
+    * removed.
+    */
+   {
+       volatile pgssSharedState *s = (volatile pgssSharedState *) pgss;
+       TimestampTz stats_reset = GetCurrentTimestamp();
+
+       SpinLockAcquire(&s->mutex);
+       s->stats.dealloc = 0;
+       s->stats.stats_reset = stats_reset;
+       SpinLockRelease(&s->mutex);
+   }
+
    /*
     * Write new empty query file, perhaps even creating a new one to recover
     * if the file was missing.
index 81915ea69bb3da9251f966ff04279e73c75b1b09..126ee31d9fdd22255a752d412d9567b86d2f729e 100644 (file)
        pg_stat_statements.max were observed
       
      
+     
+      
+       stats_reset timestamp with time zone
+      
+      
+       Time at which all statistics in the
+       pg_stat_statements view were last reset.
+      
+     
+
     
    
   
       specified, the default value 0(invalid) is used for
       each of them and the statistics that match with other parameters will be
       reset.  If no parameter is specified or all the specified parameters are
-      0(invalid), it will discard all statistics including
-      the statistics that pg_stat_statements_info
-      displays.  By default, this function can only be executed by superusers.
+      0(invalid), it will discard all statistics.
+      If all statistics in the pg_stat_statements
+      view are discarded, it will also reset the statistics in the
+      pg_stat_statements_info view.
+      By default, this function can only be executed by superusers.
       Access may be granted to others using GRANT.