Why the query is slow, drawn as a tree.
Explain Analyze is a small set of notes on Postgres performance: reading plans, choosing indexes, spotting N+1 queries, pooling connections, keeping bloat in check and changing schemas while traffic keeps flowing.
Limit
- cost
- 9131.0
- rows est / act
- 50 / 50
- time
- 143.9 ms
Hash Join o.customer_id = c.id
- cost
- 9120.5
- rows est / act
- 212 / 4871
- time
- 142.4 ms
Index Scan orders o, filter status = 'paid'
- cost
- 7018.1
- rows est / act
- 212 / 4871
- time
- 118.6 ms
46,091 rows removed by filter
Hash
- cost
- 1204.0
- rows est / act
- 51200 / 51200
- time
- 18.5 ms
Seq Scan customers c
- cost
- 1204.0
- rows est / act
- 51200 / 51200
- time
- 9.9 ms
Notes
- 26 Oct 2026Adding a column and an index without downtimePostgres migration patterns that avoid long locks: fast column adds, concurrent indexes, NOT VALID constraints, batched backfills.
- 12 Oct 2026Finding and fixing N+1 queriesHow N+1 patterns happen, how to catch them in logs and pg_stat_statements, and three ways to fix them.
- 28 Sept 2026B-tree, partial and covering indexes in PostgresWhere B-tree, partial and covering indexes help, how column order matters, and what every extra index costs on writes.
- 14 Sept 2026Reading a Postgres query plan from the bottom upA practical walk through EXPLAIN (ANALYZE, BUFFERS): tree shape, cost units, estimate errors, loops, and what to check first.