mirror of
https://github.com/postgres/postgres.git
synced 2025-10-15 05:46:52 +03:00
Add stats_reset to pg_stat_user_functions
It is possible to call pg_stat_reset_single_function_counters() for a single function, but the reset time was missing the system view showing its statistics. Like all the fields of pg_stat_user_functions, the GUC track_functions needs to be enabled to show the statistics about function executions. Bump catalog version. Bump PGSTAT_FILE_FORMAT_ID, as a result of the new field added to PgStat_StatFuncEntry. Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Discussion: https://postgr.es/m/aONjnsaJSx-nEdfU@paquier.xyz
This commit is contained in:
@@ -4736,6 +4736,15 @@ description | Waiting for a newly initialized WAL file to reach durable storage
|
|||||||
other functions called by it, in milliseconds
|
other functions called by it, in milliseconds
|
||||||
</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 these statistics were last reset
|
||||||
|
</para></entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -1131,7 +1131,8 @@ CREATE VIEW pg_stat_user_functions AS
|
|||||||
P.proname AS funcname,
|
P.proname AS funcname,
|
||||||
pg_stat_get_function_calls(P.oid) AS calls,
|
pg_stat_get_function_calls(P.oid) AS calls,
|
||||||
pg_stat_get_function_total_time(P.oid) AS total_time,
|
pg_stat_get_function_total_time(P.oid) AS total_time,
|
||||||
pg_stat_get_function_self_time(P.oid) AS self_time
|
pg_stat_get_function_self_time(P.oid) AS self_time,
|
||||||
|
pg_stat_get_function_stat_reset_time(P.oid) AS stats_reset
|
||||||
FROM pg_proc P LEFT JOIN pg_namespace N ON (N.oid = P.pronamespace)
|
FROM pg_proc P LEFT JOIN pg_namespace N ON (N.oid = P.pronamespace)
|
||||||
WHERE P.prolang != 12 -- fast check to eliminate built-in functions
|
WHERE P.prolang != 12 -- fast check to eliminate built-in functions
|
||||||
AND pg_stat_get_function_calls(P.oid) IS NOT NULL;
|
AND pg_stat_get_function_calls(P.oid) IS NOT NULL;
|
||||||
|
@@ -328,6 +328,7 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
|
|||||||
.pending_size = sizeof(PgStat_FunctionCounts),
|
.pending_size = sizeof(PgStat_FunctionCounts),
|
||||||
|
|
||||||
.flush_pending_cb = pgstat_function_flush_cb,
|
.flush_pending_cb = pgstat_function_flush_cb,
|
||||||
|
.reset_timestamp_cb = pgstat_function_reset_timestamp_cb,
|
||||||
},
|
},
|
||||||
|
|
||||||
[PGSTAT_KIND_REPLSLOT] = {
|
[PGSTAT_KIND_REPLSLOT] = {
|
||||||
|
@@ -214,6 +214,12 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pgstat_function_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
|
||||||
|
{
|
||||||
|
((PgStatShared_Function *) header)->stats.stat_reset_timestamp = ts;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* find any existing PgStat_FunctionCounts entry for specified function
|
* find any existing PgStat_FunctionCounts entry for specified function
|
||||||
*
|
*
|
||||||
|
@@ -203,6 +203,24 @@ PG_STAT_GET_FUNCENTRY_FLOAT8_MS(total_time)
|
|||||||
/* pg_stat_get_function_self_time */
|
/* pg_stat_get_function_self_time */
|
||||||
PG_STAT_GET_FUNCENTRY_FLOAT8_MS(self_time)
|
PG_STAT_GET_FUNCENTRY_FLOAT8_MS(self_time)
|
||||||
|
|
||||||
|
Datum
|
||||||
|
pg_stat_get_function_stat_reset_time(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
Oid funcid = PG_GETARG_OID(0);
|
||||||
|
TimestampTz result;
|
||||||
|
PgStat_StatFuncEntry *funcentry;
|
||||||
|
|
||||||
|
if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
|
||||||
|
result = 0;
|
||||||
|
else
|
||||||
|
result = funcentry->stat_reset_timestamp;
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
else
|
||||||
|
PG_RETURN_TIMESTAMPTZ(result);
|
||||||
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
|
pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
@@ -57,6 +57,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 202510062
|
#define CATALOG_VERSION_NO 202510081
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6071,6 +6071,10 @@
|
|||||||
proname => 'pg_stat_get_function_self_time', provolatile => 's',
|
proname => 'pg_stat_get_function_self_time', provolatile => 's',
|
||||||
proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
|
proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
|
||||||
prosrc => 'pg_stat_get_function_self_time' },
|
prosrc => 'pg_stat_get_function_self_time' },
|
||||||
|
{ oid => '8745', descr => 'statistics: last reset for a function',
|
||||||
|
proname => 'pg_stat_get_function_stat_reset_time', provolatile => 's',
|
||||||
|
proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
|
||||||
|
prosrc => 'pg_stat_get_function_stat_reset_time' },
|
||||||
|
|
||||||
{ oid => '3037',
|
{ oid => '3037',
|
||||||
descr => 'statistics: number of scans done for table/index in current transaction',
|
descr => 'statistics: number of scans done for table/index in current transaction',
|
||||||
|
@@ -212,7 +212,7 @@ typedef struct PgStat_TableXactStatus
|
|||||||
* ------------------------------------------------------------
|
* ------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB8
|
#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB9
|
||||||
|
|
||||||
typedef struct PgStat_ArchiverStats
|
typedef struct PgStat_ArchiverStats
|
||||||
{
|
{
|
||||||
@@ -384,6 +384,7 @@ typedef struct PgStat_StatFuncEntry
|
|||||||
|
|
||||||
PgStat_Counter total_time; /* times in microseconds */
|
PgStat_Counter total_time; /* times in microseconds */
|
||||||
PgStat_Counter self_time;
|
PgStat_Counter self_time;
|
||||||
|
TimestampTz stat_reset_timestamp;
|
||||||
} PgStat_StatFuncEntry;
|
} PgStat_StatFuncEntry;
|
||||||
|
|
||||||
typedef struct PgStat_StatReplSlotEntry
|
typedef struct PgStat_StatReplSlotEntry
|
||||||
|
@@ -691,6 +691,7 @@ extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, Time
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
|
extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
|
||||||
|
extern void pgstat_function_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1025,7 +1025,7 @@ test_stat_func| | |
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1_track_funcs_all s2_track_funcs_all s1_func_call s2_func_call s2_func_call2 s1_ff s2_ff s1_func_stats s2_func_call s2_func_call2 s2_ff s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset s1_func_stats s1_func_stats2 s1_func_stats
|
starting permutation: s1_track_funcs_all s2_track_funcs_all s1_func_call s2_func_call s2_func_call2 s1_ff s2_ff s1_func_stats s2_func_call s2_func_call2 s2_ff s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check s1_func_stats_reset s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check
|
||||||
pg_stat_force_next_flush
|
pg_stat_force_next_flush
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -1137,6 +1137,15 @@ name |pg_stat_get_function_calls|total_above_zero|self_above_zero
|
|||||||
test_stat_func| 3|t |t
|
test_stat_func| 3|t |t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
step s1_func_stats_reset_check:
|
||||||
|
SELECT pg_stat_get_function_stat_reset_time('test_stat_func'::regproc)
|
||||||
|
IS NOT NULL AS has_stats_reset;
|
||||||
|
|
||||||
|
has_stats_reset
|
||||||
|
---------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
step s1_func_stats_reset: SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc);
|
step s1_func_stats_reset: SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc);
|
||||||
pg_stat_reset_single_function_counters
|
pg_stat_reset_single_function_counters
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
@@ -1185,6 +1194,15 @@ name |pg_stat_get_function_calls|total_above_zero|self_above_zero
|
|||||||
test_stat_func| 0|f |f
|
test_stat_func| 0|f |f
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
step s1_func_stats_reset_check:
|
||||||
|
SELECT pg_stat_get_function_stat_reset_time('test_stat_func'::regproc)
|
||||||
|
IS NOT NULL AS has_stats_reset;
|
||||||
|
|
||||||
|
has_stats_reset
|
||||||
|
---------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1_func_stats_nonexistent s1_func_stats_reset_nonexistent s1_func_stats_nonexistent
|
starting permutation: s1_func_stats_nonexistent s1_func_stats_reset_nonexistent s1_func_stats_nonexistent
|
||||||
pg_stat_force_next_flush
|
pg_stat_force_next_flush
|
||||||
|
@@ -1025,7 +1025,7 @@ test_stat_func| | |
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1_track_funcs_all s2_track_funcs_all s1_func_call s2_func_call s2_func_call2 s1_ff s2_ff s1_func_stats s2_func_call s2_func_call2 s2_ff s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset s1_func_stats s1_func_stats2 s1_func_stats
|
starting permutation: s1_track_funcs_all s2_track_funcs_all s1_func_call s2_func_call s2_func_call2 s1_ff s2_ff s1_func_stats s2_func_call s2_func_call2 s2_ff s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check s1_func_stats_reset s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check
|
||||||
pg_stat_force_next_flush
|
pg_stat_force_next_flush
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -1137,6 +1137,15 @@ name |pg_stat_get_function_calls|total_above_zero|self_above_zero
|
|||||||
test_stat_func| 3|t |t
|
test_stat_func| 3|t |t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
step s1_func_stats_reset_check:
|
||||||
|
SELECT pg_stat_get_function_stat_reset_time('test_stat_func'::regproc)
|
||||||
|
IS NOT NULL AS has_stats_reset;
|
||||||
|
|
||||||
|
has_stats_reset
|
||||||
|
---------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
step s1_func_stats_reset: SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc);
|
step s1_func_stats_reset: SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc);
|
||||||
pg_stat_reset_single_function_counters
|
pg_stat_reset_single_function_counters
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
@@ -1185,6 +1194,15 @@ name |pg_stat_get_function_calls|total_above_zero|self_above_zero
|
|||||||
test_stat_func| 0|f |f
|
test_stat_func| 0|f |f
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
step s1_func_stats_reset_check:
|
||||||
|
SELECT pg_stat_get_function_stat_reset_time('test_stat_func'::regproc)
|
||||||
|
IS NOT NULL AS has_stats_reset;
|
||||||
|
|
||||||
|
has_stats_reset
|
||||||
|
---------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
starting permutation: s1_func_stats_nonexistent s1_func_stats_reset_nonexistent s1_func_stats_nonexistent
|
starting permutation: s1_func_stats_nonexistent s1_func_stats_reset_nonexistent s1_func_stats_nonexistent
|
||||||
pg_stat_force_next_flush
|
pg_stat_force_next_flush
|
||||||
|
@@ -58,6 +58,10 @@ step s1_track_funcs_none { SET track_functions = 'none'; }
|
|||||||
step s1_func_call { SELECT test_stat_func(); }
|
step s1_func_call { SELECT test_stat_func(); }
|
||||||
step s1_func_drop { DROP FUNCTION test_stat_func(); }
|
step s1_func_drop { DROP FUNCTION test_stat_func(); }
|
||||||
step s1_func_stats_reset { SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc); }
|
step s1_func_stats_reset { SELECT pg_stat_reset_single_function_counters('test_stat_func'::regproc); }
|
||||||
|
step s1_func_stats_reset_check {
|
||||||
|
SELECT pg_stat_get_function_stat_reset_time('test_stat_func'::regproc)
|
||||||
|
IS NOT NULL AS has_stats_reset;
|
||||||
|
}
|
||||||
step s1_func_stats_reset_nonexistent { SELECT pg_stat_reset_single_function_counters(12000); }
|
step s1_func_stats_reset_nonexistent { SELECT pg_stat_reset_single_function_counters(12000); }
|
||||||
step s1_reset { SELECT pg_stat_reset(); }
|
step s1_reset { SELECT pg_stat_reset(); }
|
||||||
step s1_func_stats {
|
step s1_func_stats {
|
||||||
@@ -235,9 +239,9 @@ permutation
|
|||||||
s1_ff s2_ff
|
s1_ff s2_ff
|
||||||
s1_func_stats
|
s1_func_stats
|
||||||
s2_func_call s2_func_call2 s2_ff
|
s2_func_call s2_func_call2 s2_ff
|
||||||
s1_func_stats s1_func_stats2 s1_func_stats
|
s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check
|
||||||
s1_func_stats_reset
|
s1_func_stats_reset
|
||||||
s1_func_stats s1_func_stats2 s1_func_stats
|
s1_func_stats s1_func_stats2 s1_func_stats s1_func_stats_reset_check
|
||||||
|
|
||||||
# test pg_stat_reset_single_function_counters of non-existing function
|
# test pg_stat_reset_single_function_counters of non-existing function
|
||||||
permutation
|
permutation
|
||||||
|
@@ -2244,7 +2244,8 @@ pg_stat_user_functions| SELECT p.oid AS funcid,
|
|||||||
p.proname AS funcname,
|
p.proname AS funcname,
|
||||||
pg_stat_get_function_calls(p.oid) AS calls,
|
pg_stat_get_function_calls(p.oid) AS calls,
|
||||||
pg_stat_get_function_total_time(p.oid) AS total_time,
|
pg_stat_get_function_total_time(p.oid) AS total_time,
|
||||||
pg_stat_get_function_self_time(p.oid) AS self_time
|
pg_stat_get_function_self_time(p.oid) AS self_time,
|
||||||
|
pg_stat_get_function_stat_reset_time(p.oid) AS stats_reset
|
||||||
FROM (pg_proc p
|
FROM (pg_proc p
|
||||||
LEFT JOIN pg_namespace n ON ((n.oid = p.pronamespace)))
|
LEFT JOIN pg_namespace n ON ((n.oid = p.pronamespace)))
|
||||||
WHERE ((p.prolang <> (12)::oid) AND (pg_stat_get_function_calls(p.oid) IS NOT NULL));
|
WHERE ((p.prolang <> (12)::oid) AND (pg_stat_get_function_calls(p.oid) IS NOT NULL));
|
||||||
|
Reference in New Issue
Block a user