EXPLAIN and EXPLAIN ANALYZE reveal MySQL’s execution plan, showing how the optimizer reads and joins tables so you can tune queries.
EXPLAIN runs the optimizer without executing the query and returns the plan it intends to use. Columns such as type
, possible_keys
, and rows
highlight join strategy, index usage, and estimated work.
Prefix your DML statement with EXPLAIN
. For example: EXPLAIN SELECT * FROM Orders;
. MySQL returns one row per table accessed, ordered by join sequence.
EXPLAIN ANALYZE
both executes the query and measures actual timing, loops, and rows-read, letting you compare estimates with reality for precise tuning.
Start with type
. Values range from system
(best) to ALL
(full scan). Check key
for chosen index and rows
for estimated row count. High row counts or ALL
signal potential problems.
Yes. Use EXPLAIN FORMAT=JSON
. The JSON object includes nested loops, cost estimates, and index condition details, which are easier to parse programmatically.
Use EXPLAIN to verify that frequent sales reports filter by indexed columns (Orders.order_date
) and join Orders
to Customers
via primary keys, avoiding costly scans that slow dashboards.
Create composite indexes that match WHERE and JOIN clauses, compare estimated rows
to reality with EXPLAIN ANALYZE
, and always analyze queries before shipping to production.
No. EXPLAIN never locks or mutates data; ANALYZE does read data but still uses shared locks only.
Yes for moderate queries. It runs the statement, so avoid on updates that modify data or extremely heavy reads during peak traffic.
Save the JSON output to a file or table, or enable performance_schema
and query events_statements_history
.