PATTERN Cited by 2 sources
EXPLAIN-driven index verification¶
Always run EXPLAIN on the query to confirm the index is
actually being used — creating an index and hoping is not a
verification. This pattern is the minimum-viable discipline
for index design: every new index is a hypothesis that the
planner will pick it up; EXPLAIN is the test that proves
the hypothesis.
Canonical framing¶
Justin Gage names the verification discipline directly:
This way of using
EXPLAINcan also be useful for debugging when creating an index, i.e. verifying that a new one is working as intended.— sources/2026-04-21-planetscale-how-do-database-indexes-work
The two EXPLAIN output columns that matter for
verification:
| Column | Meaning |
|---|---|
possible_keys |
Indexes the planner considered for this query |
key |
Index the planner actually chose |
A new index is only effective if it appears in key for
the target query — appearing in possible_keys but not
key means the planner considered and rejected it (see
concepts/index-selectivity for the standard rejection
cause).
The workflow¶
-- 1. Baseline: EXPLAIN before the index
EXPLAIN SELECT * FROM users WHERE most_recent_activity > NOW() - INTERVAL 1 DAY;
-- type: ALL, rows: 300000, key: NULL
-- 2. Create the index
CREATE INDEX activity_idx ON users(most_recent_activity);
-- 3. EXPLAIN after the index — verify
EXPLAIN SELECT * FROM users WHERE most_recent_activity > NOW() - INTERVAL 1 DAY;
-- type: range, rows: 1500, key: activity_idx ← verification success
The canonical before/after signals:
typemoves fromALL(full table scan) torange/ref/const(see concepts/mysql-access-type)rowsdrops sharplykeynames the new indexkey_len(for composite indexes) reveals how many columns are actually in use
When verification fails¶
If the new index appears in possible_keys but not key,
the planner found it but rejected it. Aaron Francis's 2023
post (sources/2026-04-21-planetscale-why-isnt-mysql-using-my-index)
enumerates eight reasons this happens:
- Considered-but-not-chosen: low selectivity, stale statistics, table-scan is cheaper
- Not-considered-at-all: leading wildcard, leftmost- prefix miss, type / charset mismatch, index obfuscation, invisibility
Each failure mode has a distinct remediation — documented on the companion patterns/explain-for-index-verification pattern, which canonicalises the verify-first-before- diagnose discipline.
Why the pattern matters¶
Three failure modes this discipline catches:
- Silent plan regression after a schema change. A
migration that alters a column's type or collation can
invalidate an existing index's use (type-mismatch
non-sargable class).
EXPLAINsurfaces this askey: NULLwhere previouslykey: idx_x. - Composite-index partial utilisation. A composite
index on
(a, b, c)may only be partially used (just the leadingacolumn).key_lenis the only signal — smaller value than expected means not all columns are engaged. - Query-pattern drift. The query shape the index was
designed for (e.g.
WHERE email = 'x') may have migrated to something the index doesn't serve (e.g.WHERE LOWER(email) = LOWER('x')— function on indexed column = index obfuscation).EXPLAINcatches the regression immediately.
Standalone EXPLAIN vs EXPLAIN ANALYZE¶
Plain EXPLAIN returns the planner's estimate — based
on statistics, without running the query. EXPLAIN ANALYZE
(MySQL 8.0.18+, Postgres since forever) actually runs
the query and reports real row counts and timings. For
index verification, plain EXPLAIN is usually sufficient —
the planner's intent is what you're verifying. Use
EXPLAIN ANALYZE when estimated rows and actual rows
diverge (stale statistics, skewed data — see
concepts/mysql-index-statistics).
Engine parity¶
| Engine | Command | Notes |
|---|---|---|
| MySQL 8.0+ | EXPLAIN, EXPLAIN ANALYZE |
Canonical output schema with possible_keys / key |
| Postgres | EXPLAIN, EXPLAIN ANALYZE |
Different output shape — planner nodes (Index Scan / Seq Scan) name the chosen index inline |
| SQL Server | SET SHOWPLAN_ALL ON / graphical plan |
Execution-plan pane in SSMS |
Seen in¶
- sources/2026-04-21-planetscale-how-do-database-indexes-work
— Justin Gage canonicalises the verify-new-index-via-
EXPLAINdiscipline as part of the index-creation workflow. Reproduces the fullEXPLAINoutput-column table withpossible_keys/keyflagged as the index-selection signals. - sources/2026-04-21-planetscale-why-isnt-mysql-using-my-index — Aaron Francis extends the pattern into a full diagnostic taxonomy when verification fails (the eight reasons MySQL ignores an expected index).
Related¶
- concepts/mysql-explain — the command
- concepts/mysql-explain-analyze — the real-cost variant
- concepts/mysql-access-type — the
typeladder the pattern reads against - concepts/index-selectivity — the most common reason
possible_keys≠key - patterns/explain-for-index-verification — the diagnostic sibling pattern (verify-first-before-diagnose)
- patterns/composite-index-for-and-predicate — a
common use of the pattern: verifying a new composite
index replaces a
type: ALLwithtype: ref,rows: 1 - systems/mysql
- systems/innodb
- systems/postgresql