隐藏索引是验证删索引影响的探针,仅修改元数据标志位,毫秒完成且不锁表;但不可见索引仍占用空间并维护写入开销,仅影响优化器选择。

隐藏索引不是架构演进的“开关”,而是验证环节的“探针”——它不改变数据模型、不切换服务流量,只让优化器临时忽略某个索引,从而安全评估删索引后的查询行为。
ALTER INDEX ... INVISIBLE 是元数据操作,不是删除
执行 ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE 仅翻转数据字典中 IS_VISIBLE 标志位,不重建 B+ 树、不锁表、不阻塞 DML。对亿级大表也能毫秒完成。
- 对比
DROP INDEX:后者需重写整个索引结构,可能卡住写入数小时,且不可逆 - 对比
CREATE INDEX:新建索引会加 S 锁,而设为不可见完全无锁 - 主键索引(含隐式主键)强制禁止设为不可见,否则报错
ERROR 3522 (HY000)或ER_PRIMARY_CANT_BE_INVISIBLE
压测时必须手动开启 use_invisible_indexes=ON
默认情况下优化器彻底忽略不可见索引,EXPLAIN 看不到它——这会导致你误以为“删掉就没事了”,但实际没验证到真实退化场景。
- 在压测连接里执行
SET SESSION optimizer_switch='use_invisible_indexes=ON' - 再跑
EXPLAIN FORMAT=JSON,检查used_indexes和key字段是否出现该索引名 - 严禁用
SET GLOBAL全局开启,会影响所有新会话,生产环境极危险 - 如果应用 SQL 中写了
FORCE INDEX(idx_name),哪怕索引不可见也会直接报错ERROR 1176
备份恢复后可见性状态可能丢失
mysqldump 默认保留 INVISIBLE 属性,但物理备份工具(如 xtrabackup)不保存该元数据。恢复后索引可能意外变回 VISIBLE,导致压测结论失效。
- 恢复后立刻查
INFORMATION_SCHEMA.STATISTICS的IS_VISIBLE列确认状态 - 分区表上对某一分区设为不可见,其他分区不受影响;但执行
ALTER TABLE ... REORGANIZE PARTITION可能重置可见性 - 不可见索引仍参与写入维护:
INSERT/UPDATE/DELETE一样更新 B+ 树页,不会降低写延迟
切 VISIBLE 前必须原子验证,且不能只信 SHOW INDEX
从不可见到可见是灰度发布的临门一脚,但很多人只看 SHOW INDEX 返回 Visible: YES 就认为搞定了,其实优化器未必真用上。
- 切换命令只有这一种:
ALTER TABLE t1 ALTER INDEX idx_name VISIBLE - 切换后立即用
EXPLAIN SELECT * FROM t1 WHERE col = ?验证是否命中,观察key字段 - 若发现性能回退,可秒级回切:
ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE - 切可见不锁表,但会触发一次元数据锁等待,务必确保没有长事务阻塞
最容易被忽略的是:不可见索引不省空间、不减写开销,只改优化器决策。想靠它“缓解负载”是典型误判——它只回答“要不要用”,不回答“要不要存”。


















