invisible索引本质是“先禁用再验证”,专为解决千万级表不敢删索引的试错难题;它仅修改is_visible元数据标志,毫秒完成、不锁表、不重建b+树,但写入开销和磁盘空间照旧,需结合慢日志与performance_schema灰度观察24小时以上。

INVISIBLE 索引不是“删不了”,而是“先不让你用”——它真正解决的是「删之前不敢试」这个卡点。对千万级表,这是唯一可落地的索引试错方式。
ALTER INDEX ... INVISIBLE 为什么能秒级完成且不锁表
因为它只改 INFORMATION_SCHEMA.STATISTICS 表里的 IS_VISIBLE 字段,不碰 B+ 树结构、不重建索引页、不加元数据锁。
对比 DROP INDEX:后者要重写整个索引,大表可能卡住写入数小时;
对比 CREATE INDEX:新建索引会加 S 锁阻塞 DML,而设为不可见完全无锁。
-
ALTER TABLE t ALTER INDEX idx_name INVISIBLE执行后立刻生效 -
SHOW INDEX FROM t \G中可见Visible: NO - 主键(含隐式主键)和唯一约束依赖的第一个唯一索引,强制设为
INVISIBLE会报错ERROR 3522
怎么验证隐藏索引是否真被优化器忽略了
默认情况下优化器彻底忽略它:EXPLAIN 不显示、FORCE INDEX(idx_name) 会直接报错 ERROR 1176。必须临时启用才能测试:
- 会话级最安全:
SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */ * FROM t WHERE ... - 全局开关
SET GLOBAL optimizer_switch = 'use_invisible_indexes=on'严禁在生产环境用 - 压测时只开这个开关还不够,得查
performance_schema.table_io_waits_summary_by_index_usage确认COUNT_STAR是否归零
隐藏索引不省空间、不减写开销,这点最容易误判
它只改优化器决策路径,不改物理维护行为:每次 INSERT/UPDATE/DELETE 仍会更新该索引的 B+ 树页,磁盘空间照占,写延迟照扣。想靠它“缓解负载”是典型误判。
- 备份恢复后可见性可能丢失:
mysqldump保留INVISIBLE属性,xtrabackup不保存,恢复后需手动查IS_VISIBLE列确认 - ORM 或应用代码里写了
USE INDEX(idx_name)的语句,设为不可见后会直接报错,上线前必须全量扫描代码和配置 - 观察周期建议 ≥24 小时,覆盖业务波峰波谷;期间异常只需一条
ALTER INDEX ... VISIBLE秒级回滚
真正难的是判断“它到底支不支撑关键路径”
不能只信单条 EXPLAIN,得盯慢日志、performance_schema 和真实 DML 延迟变化。一旦漏掉这些信号,就容易把救命索引当冗余给“藏没了”。











