EXPLAIN and query plan optimization

Maria Garcia Feb 2026
2 tabs
-- Basic EXPLAIN
EXPLAIN
SELECT * FROM users WHERE email = 'alice@example.com';

-- EXPLAIN with cost and row estimates
-- Output shows: Seq Scan on users (cost=0.00..15.50 rows=1 width=100)

-- EXPLAIN ANALYZE: Actual execution with timing
EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

-- PostgreSQL: Detailed output
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT * FROM orders WHERE user_id = 123;

-- MySQL: Extended format
EXPLAIN FORMAT=JSON
SELECT * FROM users WHERE created_at > '2024-01-01';

-- Example output analysis:
/*
Seq Scan on users  (cost=0.00..18.50 rows=10 width=100)
                   (actual time=0.012..0.034 rows=8 loops=1)
  Filter: (created_at > '2024-01-01')
  Rows Removed by Filter: 2
Planning Time: 0.123 ms
Execution Time: 0.456 ms

Key metrics:
- cost: Estimated cost (startup..total)
- rows: Estimated rows (10) vs actual rows (8)
- width: Average row size in bytes
- actual time: Real execution time
- loops: How many times node executed
*/

-- Index scan vs Sequential scan
-- Without index: Sequential Scan
EXPLAIN SELECT * FROM orders WHERE status = 'pending';
-- Seq Scan on orders (cost=0.00..50.00 rows=100)

CREATE INDEX idx_orders_status ON orders(status);

-- With index: Index Scan
EXPLAIN SELECT * FROM orders WHERE status = 'pending';
-- Index Scan using idx_orders_status (cost=0.28..8.30 rows=100)

-- Bitmap Index Scan: Combines multiple indexes
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE status = 'pending' AND created_at > CURRENT_DATE - INTERVAL '7 days';
-- Bitmap Heap Scan on orders
--   Recheck Cond: ...
--   -> BitmapAnd
--        -> Bitmap Index Scan on idx_orders_status
--        -> Bitmap Index Scan on idx_orders_created_at
2 files · sql Explain with highlit

EXPLAIN reveals database execution plans. I use EXPLAIN ANALYZE for actual runtime statistics. Understanding plan nodes—Seq Scan, Index Scan, Nested Loop, Hash Join—guides optimization. Cost estimates predict query expense. Rows estimates show expected result size. Inaccurate statistics cause poor plans—run ANALYZE regularly. Sequential scans aren't always bad for small tables. Index scans excel for selective queries. Bitmap scans combine multiple indexes. Hash joins suit large datasets. Nested loops work best with small inner tables. Sort operations indicate ORDER BY cost. Understanding execution plans is essential for performance tuning. EXPLAIN is the first step in fixing slow queries.