
怎么创建和切换不可见索引
MySQL 8.0+ 支持把索引设为 INVISIBLE,它仍被维护(插入/更新时会同步更新),但优化器默认不走它。创建时直接加 INVISIBLE 关键字就行:
CREATE INDEX idx_user_email ON users(email) INVISIBLE;
已有索引想临时“禁用”?用 ALTER TABLE ... ALTER INDEX ... INVISIBLE:
ALTER TABLE users ALTER INDEX idx_user_email INVISIBLE;
ALTER TABLE users ALTER INDEX idx_user_email VISIBLE;
注意:只有 B-tree 索引支持不可见,FULLTEXT 和 SPATIAL 不行;而且主键不能设为不可见——哪怕你试了也会报错:ERROR 3522 (HY000): A primary key index cannot be invisible。
为什么不用 DROP 而用 INVISIBLE
删索引要重建表(除非是 MySQL 5.7+ 的 ALGORITHM=INSTANT,但仅限加字段、改列名等极少数操作),而设为不可见是秒级元数据变更,不锁表、不触发索引重建。
常见误判场景:线上怀疑某个索引拖慢写入,但不敢直接删——怕查询突然变慢。这时设为 INVISIBLE,观察几天 slow_query_log 和 EXPLAIN 结果,确认没查询依赖它,再决定是否真正删除。
要点:
-
INVISIBLE索引仍消耗磁盘空间、影响 INSERT/UPDATE/DELETE 性能 - 它不会出现在
SHOW INDEX的默认结果里,得显式查:SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME = 'xxx' AND TABLE_NAME = 'users' -
FORCE INDEX无法强制走不可见索引,会报错:ERROR 1176 (42000): Key 'idx_user_email' doesn't exist in table 'users'
测试时容易忽略的 optimizer_switch 设置
MySQL 默认开启 use_invisible_indexes,所以 INVISIBLE 索引真“不可见”。但如果你在测试中想临时让优化器考虑它(比如验证“如果启用这个索引,执行计划会不会变好”),得手动打开开关:
SET SESSION optimizer_switch = 'use_invisible_indexes=on';
注意:
- 这个开关只对当前 session 生效,不影响其他连接
- 全局设置需
SET GLOBAL,但生产环境慎用,可能意外改变所有查询行为 - 开关关闭时,哪怕你写
USE INDEX(idx_user_email),也会被无视,不是报错而是静默降级到全表扫描或其它可用索引
EXPLAIN 看不见 INVISIBLE 索引,但 performance_schema 能挖出来
EXPLAIN 输出里永远看不到不可见索引——它压根不在候选索引列表里。但如果你怀疑某条慢查本该走它,又不确定是不是被设 invisble 了,可以查 performance_schema.table_io_waits_summary_by_index_usage:
SELECT OBJECT_NAME, INDEX_NAME, COUNT_READ FROM performance_schema.table_io_waits_summary_by_index_usage WHERE OBJECT_NAME = 'users' AND INDEX_NAME IS NOT NULL ORDER BY COUNT_READ DESC;
这个视图会统计每个索引的实际使用次数,包括 INVISIBLE 的——只要某次查询显式指定过(比如 FORCE INDEX),或者 session 开了 use_invisible_indexes=on,它就会被计数。
关键点:
- 该视图默认关闭收集,需提前开:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_waits_history_long'; -
COUNT_READ是累计值,重启后清零,别拿单次结果下结论 - 如果一个
INVISIBLE索引的COUNT_READ长期为 0,基本可确认没业务路径在用它
不可见索引不是“隐身术”,而是“选择性失明”——对优化器不可见,但对存储引擎、复制、备份、监控全透明。最容易翻车的地方,就是以为设成 INVISIBLE 就彻底没开销了,其实写放大和空间占用一点没少。










