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;
| Column | Meaning |
| total_exec_time | Cumulative ms |
| mean_exec_time | Avg ms per call |
| stddev_exec_time | Variance |
| rows | Total rows returned/affected |
| shared_blks_hit / read | Buffer cache vs disk |
| wal_bytes | WAL 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
| track | Captures |
| none | Disabled |
| top (default) | Top-level only |
| all | Including 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.