Query planners and join algorithms
How Postgres picks nested-loop vs hash vs merge join — and why one query is 1000x faster than another.
Same SQL query. Different plans. Different performance. The query planner picks the plan based on statistics (row counts, distinctness, correlation) and cost model (I/O, CPU, memory). Understanding this is the difference between a query that runs in 5ms and one that runs in 5 seconds.
Nested Loop
Cost: O(N × M)
Best for: Small outer (<100 rows), index on inner. Postgres default for small correlated queries.
EXPLAIN — the debugging tool
Every DB has one. Postgres's EXPLAIN (ANALYZE, BUFFERS) is the gold standard. Reads:
Two things to look for: (1) Sequential scans on big tables → missing index. (2) Wrong row estimates → run ANALYZE to update statistics.
The 5 planner behaviors every senior knows
- Stale statistics → wrong plans. Auto-vacuum handles this; disable at your peril.
- Parameterized queries with skew (WHERE status = ?) may pick wrong plan for uncommon values. Use
plan_cache_mode. - LIMIT + ORDER BY changes plans dramatically — planner assumes rows can be returned early.
- Joining 3+ tables: planner reorders. Postgres considers up to
geqo_threshold=12tables exhaustively. work_memtoo small = hash spills to disk = 100× slowdown. Tune per session for big analytical queries.
Applied in these systems
Practice what you just read
Every foundation concept has a companion quiz to close the loop.