MySQL EXPLAIN Visualizer
Paste your MySQL EXPLAIN or EXPLAIN FORMAT=JSON output and get a color-coded query plan with actionable warnings. Full table scans (type=ALL), missing indexes (key=NULL), filesorts, and temporary tables are flagged immediately. A short verdict at the bottom summarizes what to fix and where to add indexes.
How to use the MySQL EXPLAIN Visualizer
Run EXPLAIN SELECT ... or EXPLAIN FORMAT=JSON SELECT ... in your MySQL client, copy the output, and paste it here. Click Analyze Plan.
- Tabular EXPLAIN — the classic pipe-delimited table MySQL CLI prints. The visualizer parses each row and renders a clean HTML table with color-coded warnings: red for full scans (
type=ALL), orange for no index used (key=NULL), yellow for large row estimates, pink forUsing filesortorUsing temporaryin the Extra column. - FORMAT=JSON — the structured JSON output from
EXPLAIN FORMAT=JSON. The visualizer walks thequery_blocktree, extracts table access details, and showsaccess_type,key,rows_examined_per_scan,cost_info, and the same warnings. - Verdict — a one-line summary at the top tells you how many problems were found and which tables need attention. Use the per-row warning messages to guide index creation.
What does MySQL EXPLAIN show and why does it matter?
EXPLAIN is MySQL's query plan inspector — it shows how the optimizer intends to execute a SELECT (or UPDATE/DELETE) without actually running it. Each row in the output represents one step in the execution plan: a table access, a subquery, or a derived table. The most important columns are type (the join type, from worst ALL to best const/eq_ref), key (which index the optimizer chose, or NULL if none), rows (the optimizer's estimate of rows examined), and Extra (additional notes like Using filesort, Using temporary, Using index).
The join type hierarchy matters: ALL is a full table scan — every row examined, scales linearly with table size, and is almost always a bug for large tables. index is a full index scan (better, but still scans all index entries). range scans a subset of an index (good). ref/eq_ref uses an equality lookup on an index (excellent). const/system resolves to a single row at query planning time (best possible). Using filesort means MySQL must sort result rows in memory or on disk — it cannot use the index order for the ORDER BY. Using temporary means MySQL creates a temporary table, often for GROUP BY or DISTINCT on non-indexed columns.
EXPLAIN FORMAT=JSON (available since MySQL 5.6) provides the same information in structured form with additional detail: cost_info (optimizer cost estimates), rows_examined_per_scan (per-loop row estimates for nested-loop joins), and used_columns. For complex queries with subqueries or derived tables, the JSON form is easier to navigate than the flat tabular output.
Common use cases
- Identifying full table scans — spot type=ALL rows that will degrade under load and determine which columns need an index.
- Index audit — confirm that a newly added index is actually being picked up by the optimizer (key column changes from NULL to the index name).
- Query optimization — diagnose why a query is slow by checking rows estimates, filesort, and temporary table usage before profiling in production.
- ORM-generated query review — ORMs often generate queries that hit full scans on FK columns or use subqueries that create temporary tables; EXPLAIN exposes these.
- Pre-deploy query checks — run EXPLAIN on new queries in staging as part of a deployment checklist to catch slow paths before they hit production traffic.