不可见索引是什么
MySQL 8.0 支持把索引设置为 INVISIBLE:优化器在生成执行计划时视而不见,但索引结构仍然维护、仍在写入时更新。它的价值在于给「删索引」加一层安全网——先设为不可见,观察完整业务周期内的性能与执行计划变化,确认没有影响再真正 DROP;如果出现问题,一条语句改回 VISIBLE 即可恢复。主键索引不能设为不可见。
基本信息
| 适用版本 | MySQL 8.0 起(5.7 不支持) |
|---|---|
| 设置方式 | ALTER TABLE t ALTER INDEX idx INVISIBLE / VISIBLE |
| 建表时指定 | CREATE INDEX ... INVISIBLE 或索引定义加 INVISIBLE |
| 优化器开关 | use_invisible_indexes 可让优化器临时忽略不可见属性(调试用) |
| 限制 | 主键索引不可设为不可见 |
| 观察期建议 | 覆盖完整业务周期,含月末跑批与活动高峰 |
典型使用场景
- 清理冗余或低效索引前的灰度验证,避免直接 DROP 引发事故
- 评估索引真实价值:真实业务流量下观察计划变化
- 变更演练:验证某个索引下线后备份、报表任务是否受影响
- 新索引调整:先把旧索引设为不可见,验证新索引能否完全接管
- 排查优化器选择:临时屏蔽某个索引观察计划是否变好
切换与观察
切换与观察
-- 1) 设为不可见:优化器不再选它,索引仍被维护
ALTER TABLE appdb.orders ALTER INDEX idx_status INVISIBLE;
-- 2) 观察执行计划与响应时间
EXPLAIN SELECT * FROM appdb.orders WHERE status = 2;
SHOW INDEX FROM appdb.orders WHERE Key_name = 'idx_status'; # Visible 列为 NO
-- 3) 确认无影响后再删除
-- DROP INDEX idx_status ON appdb.orders;
-- 4) 有问题立即恢复可见
ALTER TABLE appdb.orders ALTER INDEX idx_status VISIBLE;确认索引状态与开关
确认索引状态与开关
-- 查看索引可见性
SELECT index_name, column_name, is_visible FROM information_schema.statistics
WHERE table_schema = 'appdb' AND table_name = 'orders';
-- 调试用:让优化器临时把不可见索引也纳入考虑(会话级)
SET SESSION optimizer_switch = 'use_invisible_indexes=on';
SET SESSION optimizer_switch = 'use_invisible_indexes=off';操作对照
| 操作 | 优化器是否使用 | 索引是否维护 | 适用阶段 |
|---|---|---|---|
| VISIBLE | 会考虑 | 维护 | 正常状态 |
| INVISIBLE | 不考虑 | 仍然维护(有写入开销) | 删除前的观察期 |
| DROP INDEX | 不适用 | 不维护 | 确认无影响后的最终动作 |
| use_invisible_indexes=on | 临时会考虑 | 维护 | 调试定位,勿长期开启 |
信息模式里用 is_visible 列查看可见性,SHOW INDEX 也有对应列;把不可见索引纳入巡检可以避免「以为删了其实还在」或「以为可见其实被设过」这类状态漂移。
不可见索引仍然占用空间并承担写入维护成本:把它当作长期挡箭牌只会白付代价。观察期结束必须二选一——要么恢复可见,要么执行 DROP,别让状态停在中间。