pg_stat_statements: Track time at which all statistics were last reset.
authorFujii Masao <[email protected]>
Fri, 18 Dec 2020 01:49:58 +0000 (10:49 +0900)
committerFujii Masao <[email protected]>
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)
        <varname>pg_stat_statements.max</varname> were observed
       </para></entry>
      </row>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>stats_reset</structfield> <type>timestamp with time zone</type>
+      </para>
+      <para>
+       Time at which all statistics in the
+       <structname>pg_stat_statements</structname> view were last reset.
+      </para></entry>
+     </row>
+
     </tbody>
    </tgroup>
   </table>
       specified, the default value <literal>0</literal>(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
-      <literal>0</literal>(invalid), it will discard all statistics including
-      the statistics that <structname>pg_stat_statements_info</structname>
-      displays.  By default, this function can only be executed by superusers.
+      <literal>0</literal>(invalid), it will discard all statistics.
+      If all statistics in the <filename>pg_stat_statements</filename>
+      view are discarded, it will also reset the statistics in the
+      <structname>pg_stat_statements_info</structname> view.
+      By default, this function can only be executed by superusers.
       Access may be granted to others using <command>GRANT</command>.
      </para>
     </listitem>