pg_stat_statements: Track time at which all statistics were last reset.

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
This commit is contained in:
Fujii Masao 2020-12-18 10:49:58 +09:00
parent 00f690a239
commit 2e0fedf036
3 changed files with 53 additions and 16 deletions

View File

@ -5,9 +5,10 @@
--- Define pg_stat_statements_info --- Define pg_stat_statements_info
CREATE FUNCTION 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' AS 'MODULE_PATHNAME'
LANGUAGE C STRICT VOLATILE PARALLEL SAFE; LANGUAGE C STRICT VOLATILE PARALLEL SAFE;

View File

@ -81,6 +81,7 @@
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/timestamp.h"
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
@ -98,7 +99,7 @@ PG_MODULE_MAGIC;
#define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat" #define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat"
/* Magic number identifying the stats file format */ /* 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 */ /* PostgreSQL major version number, changes in which invalidate all entries */
static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100; static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
@ -199,6 +200,7 @@ typedef struct Counters
typedef struct pgssGlobalStats typedef struct pgssGlobalStats
{ {
int64 dealloc; /* # of times entries were deallocated */ int64 dealloc; /* # of times entries were deallocated */
TimestampTz stats_reset; /* timestamp with all stats reset */
} pgssGlobalStats; } pgssGlobalStats;
/* /*
@ -565,6 +567,7 @@ pgss_shmem_startup(void)
pgss->n_writers = 0; pgss->n_writers = 0;
pgss->gc_count = 0; pgss->gc_count = 0;
pgss->stats.dealloc = 0; pgss->stats.dealloc = 0;
pgss->stats.stats_reset = GetCurrentTimestamp();
} }
info.keysize = sizeof(pgssHashKey); info.keysize = sizeof(pgssHashKey);
@ -1881,6 +1884,9 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
tuplestore_donestoring(tupstore); 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. * Return statistics of pg_stat_statements.
*/ */
@ -1888,6 +1894,16 @@ Datum
pg_stat_statements_info(PG_FUNCTION_ARGS) pg_stat_statements_info(PG_FUNCTION_ARGS)
{ {
pgssGlobalStats stats; 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 */ /* Read global statistics for pg_stat_statements */
{ {
@ -1898,7 +1914,10 @@ pg_stat_statements_info(PG_FUNCTION_ARGS)
SpinLockRelease(&s->mutex); 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); hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
num_remove++; 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? */ /* All entries are removed? */
if (num_entries != num_remove) if (num_entries != num_remove)
goto release_lock; 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 * Write new empty query file, perhaps even creating a new one to recover
* if the file was missing. * if the file was missing.

View File

@ -523,6 +523,16 @@
<varname>pg_stat_statements.max</varname> were observed <varname>pg_stat_statements.max</varname> were observed
</para></entry> </para></entry>
</row> </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> </tbody>
</tgroup> </tgroup>
</table> </table>
@ -549,9 +559,11 @@
specified, the default value <literal>0</literal>(invalid) is used for specified, the default value <literal>0</literal>(invalid) is used for
each of them and the statistics that match with other parameters will be 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 reset. If no parameter is specified or all the specified parameters are
<literal>0</literal>(invalid), it will discard all statistics including <literal>0</literal>(invalid), it will discard all statistics.
the statistics that <structname>pg_stat_statements_info</structname> If all statistics in the <filename>pg_stat_statements</filename>
displays. By default, this function can only be executed by superusers. 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>. Access may be granted to others using <command>GRANT</command>.
</para> </para>
</listitem> </listitem>