mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-25 13:17:41 +03:00 
			
		
		
		
	This patch adds 'stats_since' and 'minmax_stats_since' columns to the pg_stat_statements view and pg_stat_statements() function. The new min/max reset mode for the pg_stat_stetments_reset() function is controlled by the parameter minmax_only. 'stat_since' column is populated with the current timestamp when a new statement is added to the pg_stat_statements hashtable. It provides clean information about statistics collection time intervals for each statement. Besides it can be used by sampling solutions to detect situations when a statement was evicted and stored again between samples. Such a sampling solution could derive any pg_stat_statements statistic values for an interval between two samples with the exception of all min/max statistics. To address this issue this patch adds the ability to reset min/max statistics independently of the statement reset using the new minmax_only parameter of the pg_stat_statements_reset(userid oid, dbid oid, queryid bigint, minmax_only boolean) function. The timestamp of such reset is stored in the minmax_stats_since field for each statement. pg_stat_statements_reset() function now returns the timestamp of a reset as the result. Discussion: https://postgr.es/m/flat/72e80e7b160a6eb189df9ef6f068cce3765d37f8.camel%40moonset.ru Author: Andrei Zubkov Reviewed-by: Julien Rouhaud, Hayato Kuroda, Yuki Seino, Chengxi Sun Reviewed-by: Anton Melnikov, Darren Rush, Michael Paquier, Sergei Kornilov Reviewed-by: Alena Rybakina, Andrei Lepikhov
		
			
				
	
	
		
			160 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| --
 | |
| -- statement timestamps
 | |
| --
 | |
| -- planning time is needed during tests
 | |
| SET pg_stat_statements.track_planning = TRUE;
 | |
| SELECT 1 AS "STMTTS1";
 | |
|  STMTTS1 
 | |
| ---------
 | |
|        1
 | |
| (1 row)
 | |
| 
 | |
| SELECT now() AS ref_ts \gset
 | |
| SELECT 1,2 AS "STMTTS2";
 | |
|  ?column? | STMTTS2 
 | |
| ----------+---------
 | |
|         1 |       2
 | |
| (1 row)
 | |
| 
 | |
| SELECT stats_since >= :'ref_ts', count(*) FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%'
 | |
| GROUP BY stats_since >= :'ref_ts'
 | |
| ORDER BY stats_since >= :'ref_ts';
 | |
|  ?column? | count 
 | |
| ----------+-------
 | |
|  f        |     1
 | |
|  t        |     1
 | |
| (2 rows)
 | |
| 
 | |
| SELECT now() AS ref_ts \gset
 | |
| SELECT
 | |
|   count(*) as total,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_plan_time + max_plan_time = 0
 | |
|   ) as minmax_plan_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_exec_time + max_exec_time = 0
 | |
|   ) as minmax_exec_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE minmax_stats_since >= :'ref_ts'
 | |
|   ) as minmax_stats_since_after_ref,
 | |
|   count(*) FILTER (
 | |
|     WHERE stats_since >= :'ref_ts'
 | |
|   ) as stats_since_after_ref
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%';
 | |
|  total | minmax_plan_zero | minmax_exec_zero | minmax_stats_since_after_ref | stats_since_after_ref 
 | |
| -------+------------------+------------------+------------------------------+-----------------------
 | |
|      2 |                0 |                0 |                            0 |                     0
 | |
| (1 row)
 | |
| 
 | |
| -- Perform single min/max reset
 | |
| SELECT pg_stat_statements_reset(0, 0, queryid, true) AS minmax_reset_ts
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS1%' \gset
 | |
| -- check
 | |
| SELECT
 | |
|   count(*) as total,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_plan_time + max_plan_time = 0
 | |
|   ) as minmax_plan_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_exec_time + max_exec_time = 0
 | |
|   ) as minmax_exec_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE minmax_stats_since >= :'ref_ts'
 | |
|   ) as minmax_stats_since_after_ref,
 | |
|   count(*) FILTER (
 | |
|     WHERE stats_since >= :'ref_ts'
 | |
|   ) as stats_since_after_ref
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%';
 | |
|  total | minmax_plan_zero | minmax_exec_zero | minmax_stats_since_after_ref | stats_since_after_ref 
 | |
| -------+------------------+------------------+------------------------------+-----------------------
 | |
|      2 |                1 |                1 |                            1 |                     0
 | |
| (1 row)
 | |
| 
 | |
| -- check minmax reset timestamps
 | |
| SELECT
 | |
| query, minmax_stats_since = :'minmax_reset_ts' AS reset_ts_match
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%'
 | |
| ORDER BY query COLLATE "C";
 | |
|            query           | reset_ts_match 
 | |
| ---------------------------+----------------
 | |
|  SELECT $1 AS "STMTTS1"    | t
 | |
|  SELECT $1,$2 AS "STMTTS2" | f
 | |
| (2 rows)
 | |
| 
 | |
| -- check that minmax reset does not set stats_reset
 | |
| SELECT
 | |
| stats_reset = :'minmax_reset_ts' AS stats_reset_ts_match
 | |
| FROM pg_stat_statements_info;
 | |
|  stats_reset_ts_match 
 | |
| ----------------------
 | |
|  f
 | |
| (1 row)
 | |
| 
 | |
| -- Perform common min/max reset
 | |
| SELECT pg_stat_statements_reset(0, 0, 0, true) AS minmax_reset_ts \gset
 | |
| -- check again
 | |
| SELECT
 | |
|   count(*) as total,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_plan_time + max_plan_time = 0
 | |
|   ) as minmax_plan_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_exec_time + max_exec_time = 0
 | |
|   ) as minmax_exec_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE minmax_stats_since >= :'ref_ts'
 | |
|   ) as minmax_ts_after_ref,
 | |
|   count(*) FILTER (
 | |
|     WHERE minmax_stats_since = :'minmax_reset_ts'
 | |
|   ) as minmax_ts_match,
 | |
|   count(*) FILTER (
 | |
|     WHERE stats_since >= :'ref_ts'
 | |
|   ) as stats_since_after_ref
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%';
 | |
|  total | minmax_plan_zero | minmax_exec_zero | minmax_ts_after_ref | minmax_ts_match | stats_since_after_ref 
 | |
| -------+------------------+------------------+---------------------+-----------------+-----------------------
 | |
|      2 |                2 |                2 |                   2 |               2 |                     0
 | |
| (1 row)
 | |
| 
 | |
| -- Execute first query once more to check stats update
 | |
| SELECT 1 AS "STMTTS1";
 | |
|  STMTTS1 
 | |
| ---------
 | |
|        1
 | |
| (1 row)
 | |
| 
 | |
| -- check
 | |
| -- we don't check planing times here to be independent of
 | |
| -- plan caching approach
 | |
| SELECT
 | |
|   count(*) as total,
 | |
|   count(*) FILTER (
 | |
|     WHERE min_exec_time + max_exec_time = 0
 | |
|   ) as minmax_exec_zero,
 | |
|   count(*) FILTER (
 | |
|     WHERE minmax_stats_since >= :'ref_ts'
 | |
|   ) as minmax_ts_after_ref,
 | |
|   count(*) FILTER (
 | |
|     WHERE stats_since >= :'ref_ts'
 | |
|   ) as stats_since_after_ref
 | |
| FROM pg_stat_statements
 | |
| WHERE query LIKE '%STMTTS%';
 | |
|  total | minmax_exec_zero | minmax_ts_after_ref | stats_since_after_ref 
 | |
| -------+------------------+---------------------+-----------------------
 | |
|      2 |                1 |                   2 |                     0
 | |
| (1 row)
 | |
| 
 | |
| -- Cleanup
 | |
| SELECT pg_stat_statements_reset() IS NOT NULL AS t;
 | |
|  t 
 | |
| ---
 | |
|  t
 | |
| (1 row)
 | |
| 
 |