Using pg_stat_statements

1. Installing Extension

CREATE EXTENSION pg_stat_statements;

2. Configuring in postgresql.conf

shared_preload_libraries          = 'pg_stat_statements'
pg_stat_statements.max            = 10000
pg_stat_statements.track          = all
pg_stat_statements.track_planning = on

3. Viewing Query Statistics

SELECT queryid, calls, total_exec_time, mean_exec_time, rows, query
  FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 20;

4. Finding Slow Queries

SELECT mean_exec_time, calls, query
  FROM pg_stat_statements
 WHERE calls > 50 ORDER BY mean_exec_time DESC LIMIT 20;

5. Finding Frequent Queries

SELECT calls, total_exec_time, query FROM pg_stat_statements
 ORDER BY calls DESC LIMIT 20;

6. Analyzing Query Performance

ColumnMeaning
total_exec_timeCumulative ms
mean_exec_timeAvg ms per call
stddev_exec_timeVariance
rowsTotal rows returned/affected
shared_blks_hit / readBuffer cache vs disk
wal_bytesWAL generated (PG 13+)

7. Checking I/O Statistics

SELECT query, shared_blks_read, shared_blks_hit,
       temp_blks_read, temp_blks_written
  FROM pg_stat_statements ORDER BY shared_blks_read DESC LIMIT 20;

8. Resetting Statistics

SELECT pg_stat_statements_reset();

9. Setting Statement Tracking Level

trackCaptures
noneDisabled
top (default)Top-level only
allIncluding nested in functions

10. Understanding Normalized Queries

Note: Literals replaced with $N placeholders so similar queries collapse into one queryid. Reset stats after big schema/parameter changes.