ALTER INDEX INVISIBLE 秒级生效且不锁表,因其仅修改 INFORMATION_SCHEMA.STATISTICS 中 IS_VISIBLE 字段,不触碰 B+ 树、不重建索引页、不加元数据锁;而 DROP INDEX 需重写整个索引结构,可能导致千万级表写入阻塞数小时。

ALTER INDEX INVISIBLE 为什么能秒级生效且不锁表
因为它只是改 INFORMATION_SCHEMA.STATISTICS 表里的 IS_VISIBLE 字段,不碰 B+ 树、不重建索引页、不加元数据锁。对比 DROP INDEX:后者要重写整个索引结构,千万级表可能卡住写入数小时。
常见错误现象:误以为“隐藏 = 删除”,结果发现磁盘空间没少、写延迟没降——因为索引仍在被维护。
-
ALTER TABLE t ALTER INDEX idx_name INVISIBLE执行后立刻生效,SHOW INDEX FROM t \G中可见Visible: NO - 主键(含隐式主键)强制设为
INVISIBLE会报错ERROR 3522(ER_PRIMARY_CANT_BE_INVISIBLE) - 分区表上对某一分区设为不可见,其他分区不受影响;但执行
REORGANIZE PARTITION可能重置可见性
EXPLAIN 看不到隐藏索引?怎么验证它真被忽略了
默认情况下优化器彻底忽略隐藏索引: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是否归零 - 盯慢日志、DML 延迟变化——单条
EXPLAIN不足以判断关键路径是否依赖该索引
ORM 或 FORCE INDEX 语句会直接崩掉
应用代码里写了 USE INDEX(idx_name) 或 FORCE INDEX(idx_name) 的 SQL,一旦索引设为不可见,执行时直接报错 ERROR 1176。这不是警告,是硬失败。
容易踩的坑:上线前没全量扫描代码和配置,导致部分接口突然 500。
- 必须提前 grep 所有 SQL 文件、ORM 配置、DAO 层代码,找出所有显式指定该索引的语句
- 备份恢复后可见性可能丢失:
mysqldump保留INVISIBLE属性,xtrabackup不保存,恢复后需手动查IS_VISIBLE列确认 - 隐藏索引不省空间、不减写开销——这点最容易误判。它只改优化器决策路径,INSERT/UPDATE/DELETE 仍更新该索引的 B+ 树页
真正难的是判断“它到底支不支撑关键路径”
不能只信单条 EXPLAIN,得盯慢日志、performance_schema 和真实 DML 延迟变化。一旦漏掉这些信号,就容易把救命索引当冗余给“藏没了”。
观察周期建议 ≥24 小时,覆盖业务波峰波谷;期间异常只需一条 ALTER INDEX idx_name VISIBLE 秒级回滚。
最易被忽略的一点:不可见索引仍参与写入维护,想靠它“缓解负载”是典型误判——它只回答“要不要用”,不回答“要不要存”。


















