Reading pg_stat_statements: A Practical SMB Workflow
For a small engineering team without a dedicated DBA, `pg_stat_statements` is the single most useful tool for figuring out which queries actually deserve attention. The extension aggregates execution statistics for every normalized query PostgreSQL runs, but raw output is noisy. The goal isn't to read every row — it's to build a repeatable weekly or biweekly habit that surfaces the two or three queries worth fixing next.
Getting the Extension Ready
Before any analysis is possible, `pg_stat_statements` needs to be enabled in `postgresql.conf` via `shared_preload_libraries`, followed by a restart and `CREATE EXTENSION pg_stat_statements;` in the target database. Most managed Postgres providers (RDS, Cloud SQL, Supabase, Neon) ship it pre-loaded or allow enabling it without a restart, which matters for teams that can't easily schedule downtime. Once enabled, the view starts accumulating data immediately, so it's worth giving it at least a few days of normal traffic before drawing conclusions — a snapshot taken right after enabling will be dominated by cache warming and migrations, not real usage patterns.
Sorting for Signal, Not Noise
The most common mistake small teams make is sorting by `total_exec_time` and calling it done. That column is useful, but it conflates "slow query" with "query that runs constantly." A better first pass uses three views side by side:
- `total_exec_time DESC` — total time spent, which reveals the biggest aggregate cost to the database
- `mean_exec_time DESC` filtered to `calls > 50` — reveals queries that are individually slow and run often enough to matter
- `(shared_blks_hit + shared_blks_read) DESC` — reveals queries generating unusual I/O, often a proxy for missing indexes
Running all three and looking for overlap — a query appearing in two or more lists — is a fast way to separate genuine problems from statistical noise. A query with a high mean time but only three total calls is rarely worth the engineering hours; a query with a modest mean time but tens of thousands of calls per day usually is.
Turning Rows Into a Fix List
Once two or
