EXPLAIN, placed before any query, shows the plan the query planner intends to execute — without actually running it — including which scan type it will use on each table and the estimated cost. EXPLAIN ANALYZE goes further: it actually runs the query and reports the real elapsed time and row counts at each step, letting you compare the planner's estimate against reality.
Seq Scan vs Index Scan
A "Seq Scan" (sequential scan) means the engine is reading every row in the table — fine for a small table, a red flag on a large one when a WHERE clause should have let it use an index instead. An "Index Scan" means the query used an index to jump directly to matching rows.
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';
-- without an index on email:
-- Seq Scan on users (cost=0.00..1834.00 rows=1 width=64)
-- with an index on email:
-- Index Scan using idx_users_email on users (cost=0.42..8.44 rows=1 width=64)EXPLAIN ANALYZE: estimated vs actual
The planner's row-count estimate can be wrong, especially on tables whose statistics are out of date — EXPLAIN ANALYZE's "actual" numbers reveal exactly where that mismatch is, which is often the real clue to a slow query.
EXPLAIN ANALYZE
SELECT customers.name, COUNT(orders.id)
FROM customers
JOIN orders ON customers.id = orders.customer_id
GROUP BY customers.name;
-- output includes lines like:
-- Hash Join (cost=15.50..45.00 rows=200 width=40) (actual time=0.5..2.1 rows=180 loops=1)
-- -> estimated 200 rows, actually got 180 — reasonably close, planner is trustworthy hereReading a plan bottom-up
Execution plans are trees, read from the innermost (bottom) operations outward — the deepest indented lines run first, feeding their results up into the operations above them. The step with the highest actual time, or the biggest gap between estimated and actual rows, is usually where to focus optimization effort first.