Reading a query plan
Before a database runs your query, it makes a plan: which tables to read, in what order, how
to join them. EXPLAIN shows you that plan without running the query:
EXPLAIN
SELECT c.name, COUNT(*)
FROM customers c
JOIN orders o ON o.customer_id = c.id
GROUP BY c.nameRead it from the bottom up. The boxes at the bottom read tables (SEQ_SCAN means reading the
whole table); above them, HASH_JOIN matches the rows and HASH_GROUP_BY totals them.
EXPLAIN ANALYZE runs the query too, and adds how long each step took and how many rows went
through it.
Most slow queries in business reporting come from a few habits:
- Joining without the right
ONcondition, which multiplies rows. Check row counts after each join. - Selecting far more than you need.
SELECT *from a wide table, when you need three columns. - Wrapping a filtered column in a function.
WHERE year(order_date) = 2025makes many databases look at every row;WHERE order_date >= '2025-01-01' AND order_date < '2026-01-01'lets them jump straight to the range. - Repeating the same subquery in several places, instead of working it out once in a CTE.