不可见索引本身不加速查询,仅让优化器忽略它以安全验证删除影响;须用alter table ... alter index ... invisible秒级切换,主键不可设为不可见,验证需查information_schema.statistics.is_visible=no,force index会报错且必须提前清理。

不可见索引本身不加速查询,但它能让你在不重建索引的前提下,安全验证“删掉这个索引会不会出事”——这才是它在索引下线流程里的真实价值。
怎么把现有索引设为不可见
用 ALTER TABLE ... ALTER INDEX ... INVISIBLE 切换,秒级完成,不锁表、不重建索引:
- 语法必须严格:只有
ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE合法;写成SET INVISIBLE或MODIFY INDEX会报ERROR 1064 (42000) - 主键索引(含隐式主键)禁止设为不可见,执行直接失败:
ERROR 3522 (HY000): Primary key cannot be invisible - 唯一约束(
UNIQUE KEY)可以设为不可见,但 INSERT/UPDATE 仍会检查该约束,失败风险不变 - 操作只改
INFORMATION_SCHEMA.STATISTICS表里的IS_VISIBLE字段,长事务未提交时会被元数据锁(MDL)阻塞
为什么 SHOW INDEX 可能骗你
SHOW INDEX FROM t1 在 MySQL 8.0+ 中确实新增了 Visible 列,但很多运维脚本、旧版客户端或 ORM 工具硬编码列顺序,会漏掉它,导致你以为索引还是可见的。
真正可靠的检查方式是查系统表:
SELECT INDEX_NAME, IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't1' AND INDEX_NAME = 'idx_name';
返回 IS_VISIBLE = 'NO' 才算成功。别信 SHOW INDEX 的视觉判断。
FORCE INDEX 会绕过不可见性,必须提前清理
这是最常踩的坑:应用代码、ORM 配置或 SQL 注释里写了 FORCE INDEX (idx_name),哪怕索引已设为不可见,MySQL 仍会尝试强制使用它,并大概率报错:ERROR 1176 (42000): Key 'idx_name' doesn't exist in table 't1'。
- 这不是语法错误,而是优化器在“可见性过滤”阶段已将该索引注销,
FORCE指令找不到目标 - 必须在设为不可见前,全局扫描所有 SQL、配置文件、ORM 映射层,移除所有
FORCE INDEX、USE INDEX提示 - 备份恢复后,
mysqldump默认保留可见性,但xtrabackup等物理备份工具可能不保留,恢复后状态可能意外回滚为VISIBLE
压测时如何确认索引真被忽略了
不能只看 EXPLAIN,得闭环验证执行计划是否真的退化:
- 先设索引为不可见:
ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE - 在压测连接中临时开启隐形索引可见性:
SET SESSION optimizer_switch='use_invisible_indexes=ON' - 对比开/关该开关下的
EXPLAIN FORMAT=JSON输出,重点看key字段是否消失、used_indexes是否不含该索引名 - 注意:
use_invisible_indexes=ON是调试开关,生产环境严禁全局开启(SET GLOBAL),只对当前 session 有效
真正难的不是命令怎么敲,而是确认所有 FORCE 提示已被清除、所有备份/恢复路径已对齐、所有分区表 DDL 不会意外重置可见性——这些细节一漏,就不是“可回滚”,而是“回滚不了”。











