Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i4Lny-0002Hu-8f for pgsql-hackers@arkaria.postgresql.org; Sun, 01 Sep 2019 09:05:50 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1i4Lmy-0006tS-2T for pgsql-hackers@arkaria.postgresql.org; Sun, 01 Sep 2019 09:04:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i4Lmx-0006tL-Q2 for pgsql-hackers@lists.postgresql.org; Sun, 01 Sep 2019 09:04:47 +0000 Received: from mx2.pinaraf.info ([2001:41d0:a:2db3::2014]) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1i4Lmq-0003pl-Vc for pgsql-hackers@postgresql.org; Sun, 01 Sep 2019 09:04:46 +0000 Received: from peanuts2.localnet (unknown [IPv6:2001:41d0:fe26:9c00:428d:5cff:fee6:7805]) by mx2.pinaraf.info (Postfix) with ESMTPSA id 46LnN54ZFxzVCVD for ; Sun, 1 Sep 2019 11:04:37 +0200 (CEST) From: Pierre Ducroquet To: pgsql-hackers Subject: [Patch] Add a reset_computed_values function in pg_stat_statements Date: Sun, 01 Sep 2019 11:04:36 +0200 Message-ID: <1762890.8ARNpCrDLI@peanuts2> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart54047663.qFHcHZVkGV" Content-Transfer-Encoding: 7Bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --nextPart54047663.qFHcHZVkGV Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Hello pg_stat_statements is a great tool to track performance issue in live databases, especially when adding interfaces like PoWA on top of it. But so far, tools like PoWA can not track the min_time, max_time, mean_time and sum_var_time of queries : these statistics are cumulated over time, fetching points in time would be of little to no use, especially when looking at the impact of a DDL change. This patch thus introduces a simple pg_stat_statements_reset_computed_values function that reset the computed statistics, leaving all other information alive, thus allowing the aforementioned scenario. Regards Pierre Ducroquet --nextPart54047663.qFHcHZVkGV Content-Disposition: attachment; filename="0001-Add-a-function-to-reset-the-cumulative-statistics.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0001-Add-a-function-to-reset-the-cumulative-statistics.patch" From 5e6d16d738e5279968321c5f3695e72ded2432db Mon Sep 17 00:00:00 2001 From: Pierre Date: Thu, 14 Feb 2019 14:37:48 +0100 Subject: [PATCH] Add a function to reset the cumulative statistics pg_stat_statements has two parts : raw statistics that are simple 'stable' counters, and computed statistics (averages, min time, max time...) When using pg_stat_statements to find and fix performance issues, being able to reset the computed statistics can help track the issue and the impact of the fixes. This would also make it possible for tools like powa to collect these statistics too and track them over time by resetting them after each collection. --- .../pg_stat_statements--1.7--1.8.sql | 11 ++++ .../pg_stat_statements/pg_stat_statements.c | 52 +++++++++++++++++-- .../pg_stat_statements.control | 2 +- 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 contrib/pg_stat_statements/pg_stat_statements--1.7--1.8.sql diff --git a/contrib/pg_stat_statements/pg_stat_statements--1.7--1.8.sql b/contrib/pg_stat_statements/pg_stat_statements--1.7--1.8.sql new file mode 100644 index 0000000000..7690a9ceba --- /dev/null +++ b/contrib/pg_stat_statements/pg_stat_statements--1.7--1.8.sql @@ -0,0 +1,11 @@ +/* contrib/pg_stat_statements/pg_stat_statements--1.7--1.8.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_stat_statements UPDATE TO '1.8'" to load this file. \quit + +CREATE FUNCTION pg_stat_statements_reset_computed_values() +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C PARALLEL SAFE; + + diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 221b47298c..3a6c227a80 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -150,6 +150,7 @@ typedef struct Counters double max_time; /* maximum execution time in msec */ double mean_time; /* mean execution time in msec */ double sum_var_time; /* sum of variances in execution time in msec */ + int64 computed_calls; /* # of times executed considered for the previous computed values */ int64 rows; /* total # of retrieved or affected rows */ int64 shared_blks_hit; /* # of shared buffer hits */ int64 shared_blks_read; /* # of shared disk blocks read */ @@ -289,6 +290,7 @@ static bool pgss_save; /* whether to save stats across shutdown */ void _PG_init(void); void _PG_fini(void); +PG_FUNCTION_INFO_V1(pg_stat_statements_reset_computed_values); PG_FUNCTION_INFO_V1(pg_stat_statements_reset); PG_FUNCTION_INFO_V1(pg_stat_statements_reset_1_7); PG_FUNCTION_INFO_V1(pg_stat_statements_1_2); @@ -1252,8 +1254,9 @@ pgss_store(const char *query, uint64 queryId, e->counters.usage = USAGE_INIT; e->counters.calls += 1; + e->counters.computed_calls += 1; e->counters.total_time += total_time; - if (e->counters.calls == 1) + if (e->counters.computed_calls == 1) { e->counters.min_time = total_time; e->counters.max_time = total_time; @@ -1268,7 +1271,7 @@ pgss_store(const char *query, uint64 queryId, double old_mean = e->counters.mean_time; e->counters.mean_time += - (total_time - old_mean) / e->counters.calls; + (total_time - old_mean) / e->counters.computed_calls; e->counters.sum_var_time += (total_time - old_mean) * (total_time - e->counters.mean_time); @@ -1324,7 +1327,7 @@ pg_stat_statements_reset_1_7(PG_FUNCTION_ARGS) } /* - * Reset statement statistics. + * Reset all statement statistics. */ Datum pg_stat_statements_reset(PG_FUNCTION_ARGS) @@ -1334,6 +1337,49 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * Reset computed statistics from all statements. + */ +Datum +pg_stat_statements_reset_computed_values(PG_FUNCTION_ARGS) +{ + if (!pgss || !pgss_hash) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("pg_stat_statements must be loaded via shared_preload_libraries"))); + entry_reset_computed(); + PG_RETURN_VOID(); +} + + +/* + * Reset statement computed statistics. + * This takes a shared lock only on the hash table, and a lock per entry + */ +static void +entry_reset_computed(void) +{ + HASH_SEQ_STATUS hash_seq; + pgssEntry *entry; + + /* Lookup the hash table entry with shared lock. */ + LWLockAcquire(pgss->lock, LW_SHARED); + + hash_seq_init(&hash_seq, pgss_hash); + while ((entry = hash_seq_search(&hash_seq)) != NULL) + { + SpinLockAcquire(&entry->mutex); + entry->counters.computed_calls = 0; + entry->counters.min_time = 0; + entry->counters.max_time = 0; + entry->counters.mean_time = 0; + entry->counters.sum_var_time = 0; + SpinLockRelease(&entry->mutex); + } + + LWLockRelease(pgss->lock); +} + /* Number of output arguments (columns) for various API versions */ #define PG_STAT_STATEMENTS_COLS_V1_0 14 #define PG_STAT_STATEMENTS_COLS_V1_1 18 diff --git a/contrib/pg_stat_statements/pg_stat_statements.control b/contrib/pg_stat_statements/pg_stat_statements.control index 14cb422354..7fb20df886 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.control +++ b/contrib/pg_stat_statements/pg_stat_statements.control @@ -1,5 +1,5 @@ # pg_stat_statements extension comment = 'track execution statistics of all SQL statements executed' -default_version = '1.7' +default_version = '1.8' module_pathname = '$libdir/pg_stat_statements' relocatable = true -- 2.23.0.rc1 --nextPart54047663.qFHcHZVkGV--