mysql 8.0 的 invisible index 是为安全验证删索引影响而设:仅对优化器不可见,仍维持更新、约束校验与磁盘占用;alter index invisible 毫秒完成,支持快速“软禁”观察真实负载,但 primary key 不可隐藏,压测需手动启用 use_invisible_indexes,备份恢复后可见性可能丢失。

MySQL 8.0 引入 INVISIBLE INDEX 不是为了“省空间”或“减写入开销”,而是为了解决一个非常实际的运维卡点:删索引前不敢试,试了又怕回不来。
隐藏索引只对优化器不可见,其他照常运行
设为 INVISIBLE 后,这个索引在 EXPLAIN 里不会出现,SELECT 也不会走它,连 FORCE INDEX(idx_name) 都会直接报错 ERROR 1176 (HY000): Key 'xxx' doesn't exist。但它依然被 INSERT/UPDATE/DELETE 实时更新,磁盘空间照占,UNIQUE 约束照校验——重复值照样报错。唯一可靠判断方式是查 INFORMATION_SCHEMA.STATISTICS 或执行 SHOW INDEX FROM t\G,看 Visible: NO 字段。
ALTER INDEX INVISIBLE 是毫秒级元数据操作,不是删索引
和 DROP INDEX 相比,它不重建 B+ 树、不锁表、不阻塞 DML,大表也能瞬时完成。这意味着你可以快速“软禁”一个索引,观察真实业务负载下的影响,而不是靠单条 EXPLAIN 猜测。但要注意:PRIMARY KEY 和隐式主键(比如 NOT NULL UNIQUE 列)强制不允许设为 INVISIBLE,否则报错 ER_PRIMARY_CANT_BE_INVISIBLE 或 ERROR 3522。
压测必须手动打开 use_invisible_indexes=ON 才能验证效果
默认情况下优化器彻底无视不可见索引,所以你不能只靠 EXPLAIN 判断“删掉它会不会变慢”。要闭环验证,得在会话级临时启用:SET SESSION optimizer_switch = 'use_invisible_indexes=on';,再跑目标 SQL 的 EXPLAIN FORMAT=JSON,检查 used_indexes 和 key 字段是否命中该索引。切记别用 GLOBAL,会污染其他连接;也别漏掉代码里硬写的 FORCE INDEX,它们会在设为不可见后立刻炸出来。
备份恢复后可见性状态可能丢失
mysqldump 默认保留 INVISIBLE 属性,但物理备份工具(如 xtrabackup)不保存该元数据。恢复后索引可能意外变回 VISIBLE,导致你之前压测的结论完全失效。上线前务必确认:SELECT IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t' AND INDEX_NAME='idx_name';。分区表上对某一分区设为不可见,其他分区不受影响;但执行 ALTER TABLE ... REORGANIZE PARTITION 可能重置整个表的可见性。
最易被忽略的一点:不可见索引不省空间、不减写延迟,它只改优化器决策路径。想靠它“缓解高负载”是典型误判——它回答的是“要不要用”,不是“要不要存”。











