EXPLAIN & Query Optimization
16. EXPLAIN & Query Optimization
Section titled “16. EXPLAIN & Query Optimization”Understanding EXPLAIN
Section titled “Understanding EXPLAIN”EXPLAIN SELECT e.name, d.dept_nameFROM employees eJOIN departments d ON e.dept_id = d.dept_idWHERE e.salary > 70000;EXPLAIN output columns:
| Column | Meaning |
|---|---|
id | Query step ID |
select_type | SIMPLE, SUBQUERY, DERIVED, UNION |
table | Table being accessed |
type | Access type (best → worst) |
possible_keys | Indexes that could be used |
key | Index actually used |
key_len | Length of index used |
rows | Estimated rows examined |
filtered | % of rows after WHERE filter |
Extra | Additional info |
Access Types (type column) — Best to Worst
Section titled “Access Types (type column) — Best to Worst”system → single row in MyISAM/MEMORY (best)const → at most one matching row (PK/unique lookup)eq_ref → one row per join row (PK/unique join)ref → multiple rows per join (non-unique index)range → index range scan (BETWEEN, <, >, IN)index → full index scan (better than ALL)ALL → full table scan (WORST — avoid!)-- Use EXPLAIN ANALYZE (MySQL 8.0.18+) for actual execution statsEXPLAIN ANALYZE SELECT * FROM employees WHERE dept_id = 1;
-- Use FORMAT=JSON for more detailEXPLAIN FORMAT=JSON SELECT * FROM employees WHERE salary > 50000;Reading EXPLAIN — Red Flags
Section titled “Reading EXPLAIN — Red Flags”-- ❌ BAD: type = ALL (full table scan)EXPLAIN SELECT * FROM employees WHERE YEAR(hire_date) = 2020;
-- ✅ FIX: use range condition for indexEXPLAIN SELECT * FROM employeesWHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31';
-- ❌ BAD: Extra = "Using filesort" on large tablesEXPLAIN SELECT * FROM employees ORDER BY salary;-- Fix: Add index on salary
-- ❌ BAD: Extra = "Using temporary"EXPLAIN SELECT dept_id, COUNT(*) FROM employees GROUP BY dept_id;-- Fix: Add index on dept_id