PostgreSQL EXPLAIN ANALYZE Reader
Paste PostgreSQL EXPLAIN ANALYZE output and see which plan nodes take the time, where row estimates are off and which sorts and hashes spill to disk.
Free · No sign-up · Your inputs stay in your browser
Input
Read a PostgreSQL EXPLAIN ANALYZE plan
Output
6 plan nodes
| Node | Self ms | Share | Rows (est) |
|---|---|---|---|
| Hash Join | 192.10 | 46.6% | 498,211 (500,000) |
| Seq Scan on orders o | 148.33 | 36.0% | 498,211 (500,000) |
| HashAggregate | 71.31 | 17.3% | 97 (100) |
| Hash | 0.47 | 0.1% | 1,000 (1,000) |
| Seq Scan on customers c | 0.31 | 0.1% | 1,000 (1,000) |
| Sort | 0.05 | 0.0% | 97 (100) |
Planning Time: 0.412 ms; Execution Time: 412.701 ms
Time per node is exclusive: the node's own actual time × loops, minus its children's. That is where the query spends its time; the top node's inclusive time is just the total. Run with EXPLAIN (ANALYZE, BUFFERS) to see whether the time went to reading from disk.
Runs in this browser. Nothing you paste is sent to a server.
About this tool
Method, assumptions, practical next steps, and limits.
Read exclusive time, not the top line
The time on each line of EXPLAIN ANALYZE includes everything below it, and is per loop. Multiplying by loops and subtracting the children gives the time the node itself spent, which is where to look. The Using EXPLAIN chapter explains every field.
Misestimates cause bad plans
The planner picks join methods from estimated row counts. When it expects 10 rows and gets 100,000, it chooses a nested loop that runs 100,000 times. ANALYZE table refreshes statistics; for correlated columns, CREATE STATISTICS teaches the planner how they relate.