CONCEPT Cited by 2 sources
MySQL invisible index¶
A MySQL invisible index is a secondary index that physically exists and is maintained on every write, but is hidden from the query optimiser — so no query plan will use it. Introduced in MySQL 8.0, invisible indexes are the canonical reversible drop-test primitive: a way to measure "what would happen to query performance if I dropped this index?" without actually dropping it.
ALTER TABLE your_table_name ALTER INDEX your_index_name INVISIBLE;
-- Run production workload, measure affected queries.
-- If performance degrades, flip back:
ALTER TABLE your_table_name ALTER INDEX your_index_name VISIBLE;
-- If performance is fine, commit the drop:
ALTER TABLE your_table_name DROP INDEX your_index_name;
(Source: sources/2026-04-21-planetscale-what-are-the-disadvantages-of-database-indexes)
Why it exists¶
Dropping an index is destructive and hard to reverse under production workloads: recreating a dropped index on a large table can take hours and place heavy load on the server. If you drop an index and discover a critical query was silently relying on it, the recovery window is long.
Invisible indexes invert the risk profile by decoupling the decision from the destructive act:
- Drop candidate chosen (e.g. via the
information_schema.STATISTICScardinality = 0 heuristic or production query-level telemetry). - Flip invisible — zero-cost metadata change.
- Measure — run production workload; watch for latency regressions, slow-query-log entries, rows-read jumps.
- Decide: if invisible-state performance is acceptable,
DROP INDEXis safe; if any query regresses, flip back to visible and the system is restored instantly.
The invisibility window is the reversible staging ground between "I think we can drop this" and the irreversible act.
Mechanics¶
- Invisible indexes remain maintained on every write —
INSERT/UPDATE/DELETEstill walk the index B+tree. Making an index invisible does not eliminate its write-amplification cost — it eliminates only its read-path benefit. This is the key difference from drop. - Storage cost preserved — the B+tree still exists on disk.
- Query optimiser blind —
EXPLAINwill not show the invisible index inpossible_keys. - Metadata-only
ALTER— the flip is instant; no table rebuild, no replica lag. SET optimizer_switch='use_invisible_indexes=on'is a session-scoped escape hatch that lets DBAs query as if the index were visible, for pre-flip planner analysis. (Not surfaced in the Lien post; MySQL 8.0 native feature.)- Primary indexes cannot be made invisible. Only secondary indexes are eligible.
Invisibility vs drop — comparison¶
| Property | Visible | Invisible | Dropped |
|---|---|---|---|
| B+tree exists on disk | Yes | Yes | No |
| Storage cost | Yes | Yes | No |
| Write amplification | Yes | Yes | No |
| Queries can use it | Yes | No | No |
| Reversible | n/a | Yes (instant flip) | No (recreate required) |
Metadata-only ALTER |
n/a | Yes | Yes (but free space reclamation can be slow) |
PlanetScale operational integration¶
On PlanetScale specifically, invisible-index DDL routes through the deploy request workflow by default — "we don't allow direct DDL on production branches, unless they have safe migrations disabled (not recommended)" — with the redemption that PlanetScale's Revert feature lets operators "simply click the 'Revert' button if you decide you want to undo an altered or dropped index and it will be reverted near instantaneously" (Source: sources/2026-04-21-planetscale-what-are-the-disadvantages-of-database-indexes).
The invisible-index mechanism is therefore doubly reversible on PlanetScale: (1) the native MySQL visibility flip, plus (2) PlanetScale's instant schema revert of the schema-change deploy itself — two independent levels of safety net for index lifecycle decisions.
Distinction from invisible columns¶
MySQL's invisible
columns (same "invisible" terminology, different
primitive) are a SELECT * / INSERT INTO t VALUES (…)
discovery mechanism for deprecating columns — the column
physically exists and explicit-column SQL still accesses it,
but default-column expansion skips it. Invisible columns are
a discovery primitive for "who is still reading this
column?"; invisible indexes are a validation primitive for
"what happens to queries if I drop this index?"
Both are MySQL-8.0 reversible-staging mechanisms for
destructive operations (DROP COLUMN / DROP INDEX), but
they work at different altitudes:
| Invisible column | Invisible index | |
|---|---|---|
| Hides from | SELECT * expansion |
Query optimiser |
| Explicit name still works | Yes | No (optimiser ignores it) |
| Write cost preserved | Yes | Yes |
| Purpose | Find SELECT * callers |
Simulate drop safely |
| Pre-drop stage | Step 6 of expand-migrate-contract | Validation before DROP INDEX |
Anti-patterns¶
- Indefinite invisibility. The point is to measure
quickly and either commit (
DROP INDEX) or revert (VISIBLE). Leaving the candidate invisible for weeks pays the storage + write-amplification cost without the read benefit — worst of all worlds. - Invisibility as throttle. Using invisibility to "temporarily disable" an index during a load spike is not what it's for — the index still costs write amplification during the invisibility window. If you want to throttle write load, you need to actually drop the indexes (and pay the recreate cost) or restructure the workload.
- Single-point measurement. One-hour invisible window on a workload that has daily/weekly/monthly peaks will miss the batch job or quarterly report that uses the index. Measure across at least one full workload cycle.
- Invisibility without
slow_query_logmonitoring. The invisible-state measurement is only as good as the instrumentation. If slow-query captures are off, the validation window can pass without detecting a latent p99.9 regression on a rare query.
Seen in¶
-
sources/2026-04-21-planetscale-why-isnt-mysql-using-my-index — Aaron Francis (PlanetScale, 2023-05-04) names invisible indexes as reason #7 in his eight-reason taxonomy of why MySQL silently ignores an index. The framing is diagnostic: "This is perhaps the least common reason your index wouldn't be used, but it is possible!" Read
SHOW INDEXESVisiblecolumn before blaming more subtle causes (selectivity, stats, leftmost-prefix misses, obfuscation). Pairs with the 2023-02-17 Lien post below as the create + diagnose sides of the same MySQL 8.0 primitive. -
sources/2026-04-21-planetscale-what-are-the-disadvantages-of-database-indexes — JD Lien (PlanetScale, 2023-02-17) canonicalises the invisible-index mechanism as step 2 of the two-step safe-drop workflow: (1) detect unused-index candidates via the
information_schema.STATISTICScardinality = 0 heuristic; (2) flip candidate toINVISIBLE, measure, thenDROP INDEXif safe (orVISIBLEto revert). Canonical framing verbatim: "With invisible indexes, you can keep the index intact but essentially hide the index from MySQL so that queries do not use the index. This gives you a way to quickly test the impact of removing an index without completely destroying it." Also discloses the PlanetScale deploy-request wrinkle (direct DDL is blocked on production branches — invisibility flip goes through deploy requests) and composes with schema revert as a two-layer safety net.
Related¶
- systems/mysql — MySQL 8.0+; feature introduced in 8.0.
- systems/innodb — InnoDB remains the index implementation substrate; invisibility is a planner-level filter above the B+tree.
- concepts/secondary-index — what invisible indexes are: hide-able secondary indexes. Primary indexes cannot be made invisible.
- concepts/mysql-invisible-column — sibling MySQL 8.0 invisibility primitive, at a different altitude.
- concepts/schema-revert — PlanetScale's second-order reversibility: even the invisible-index DDL itself is revertible via deploy-request revert.
- patterns/cardinality-based-unused-index-detection — the detection half of the safe-drop workflow; invisible indexes are the validation half.