隐藏索引仅修改数据字典的is_visible标志,毫秒级生效,不重建b+树、不锁表、不阻塞写入;但仍消耗磁盘空间并承担写维护开销,且force index会使其失效。

隐藏索引不是“删索引”,而是“关开关”
它不重建 B+ 树、不锁表、不阻塞写入,执行 ALTER INDEX idx_name INVISIBLE 仅修改数据字典里的 IS_VISIBLE 标志,毫秒级完成。对千万级大表,这直接绕开了 DROP INDEX 可能数小时的不可控窗口——你不是在删索引,是在给优化器下指令:“这个别用”。
压测时必须手动打开 use_invisible_indexes
默认情况下,EXPLAIN 完全看不到隐藏索引,哪怕它物理存在。想验证“删掉它会不会变慢”,必须临时启用:
- 单条 SQL 级别(推荐):
SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */ ... - 全局开启(仅限测试环境):
SET GLOBAL optimizer_switch = 'use_invisible_indexes=on';生产环境严禁,会影响所有新会话 - 验证是否生效:查
EXPLAIN FORMAT=JSON输出里的used_indexes或key字段是否含该索引名
FORCE INDEX 会直接让隐藏索引“破防”
如果应用代码或 ORM 中硬写了 FORCE INDEX(idx_name),哪怕索引已设为 INVISIBLE,MySQL 仍会报错 ERROR 1176 (HY000)。这意味着:
- 上线前必须全量扫描 SQL 和配置,清理所有显式索引提示
- 不能只靠 DDL 操作就认为“安全了”,业务层耦合才是最大盲区
- 灰度期间若发现慢查询突增,优先检查是否有
FORCE/USE/IGNORE提示残留
不可见 ≠ 不维护,空间和写开销照旧
这是最容易被忽略的一点:隐藏索引仍参与所有写操作维护——INSERT/UPDATE/DELETE 都会更新它的 B+ 树页。它不省磁盘空间,也不降低写延迟,只改变优化器决策路径。想靠它“缓解高负载”是误判;它只回答“要不要用”,不回答“要不要存”。











