不可见索引是安全试错机制而非性能优化工具,创建须用CREATE INDEX ... INVISIBLE或ALTER TABLE ... ALTER INDEX ... INVISIBLE,主键等特殊索引不支持,EXPLAIN默认不显示,验证需查INFORMATION_SCHEMA并比对执行计划,FORCE INDEX对其无效,写入开销不变。

不可见索引不是性能优化工具,而是安全试错机制:它让优化器默认跳过某个索引,但写入开销、磁盘占用、唯一性校验全在——你看到的“变慢”,才是它真实影响的起点。
怎么创建或切换为不可见索引
只有 CREATE INDEX ... INVISIBLE 和 ALTER TABLE ... ALTER INDEX ... INVISIBLE 两种合法方式,其他写法(如 SET INVISIBLE、MODIFY INDEX)直接报错 ERROR 1064 或 ERROR 3522。
- 新建即隐藏最稳妥:
CREATE INDEX idx_order_status ON orders(status) INVISIBLE; - 已有索引切换必须用标准 DDL:
ALTER TABLE orders ALTER INDEX idx_user_id INVISIBLE; - 主键、首个
UNIQUE NOT NULL列(隐式主键)、FULLTEXT、SPATIAL索引不支持,执行会立刻报ERROR 3522 - 操作是元数据级变更,毫秒完成,但高并发写入时可能短暂等待 MDL 锁,建议避开流量高峰
为什么 EXPLAIN 看不到该索引,以及如何验证它真被忽略
EXPLAIN 默认不列出不可见索引,这不是 bug,是设计行为——优化器在生成执行计划前就把它过滤掉了。验证是否生效,必须交叉比对两处:
- 查系统表确认状态:
SELECT IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 'orders' AND INDEX_NAME = 'idx_user_id';返回字符串'NO'才算设置成功 - 跑真实查询看执行计划:
EXPLAIN SELECT * FROM orders WHERE user_id = 123;若之前走idx_user_id,现在key为空或换成其他索引,才说明生效 - 别信
SHOW INDEX FROM orders\G的Comment字段(恒为NULL),也别只看Visible: NO——旧版客户端或硬编码脚本可能漏掉该字段 - 若仍走该索引,先查
SELECT @@optimizer_switch LIKE '%use_invisible_indexes=on%';,返回1就说明会话或全局开了开关
FORCE INDEX 或 USE INDEX 对不可见索引无效
这是最容易误判的点:FORCE INDEX (idx_user_id) 不会强制使用不可见索引,而会直接报错 ERROR 1176 (HY000): Key 'idx_user_id' doesn't exist in table 'orders'。MySQL 在解析 hint 前已将不可见索引从候选集移除。
- 想临时启用不可见索引做对比?只能显式打开开关:
SET SESSION optimizer_switch = 'use_invisible_indexes=on'; - 更安全的方式是 SQL 级提示(8.0.22+):
SELECT /*+ SET_VAR(optimizer_switch = "use_invisible_indexes=on") */ * FROM orders WHERE user_id = 123; - 灰度测试前必须全局扫描代码、ORM 配置、存储过程,移除所有硬编码的
FORCE INDEX或USE INDEX,否则测试完全失真 - 备份还原后行为可能突变:
mysqldump默认不导出INVISIBLE关键字,还原后索引自动变回VISIBLE
压力测试时真正要盯的指标
不能只看单条 EXPLAIN,得在真实负载下观测三类信号是否同步出现:
- 慢查询日志里,原本走该索引的语句
Query_time明显升高,或首次出现新慢 SQL -
performance_schema.table_io_waits_summary_by_index_usage中对应索引的COUNT_STAR归零(仅作参考,该表重启清零) -
Handler_read_next、Handler_read_rnd_next指标陡增——这是退化为全表扫描或文件排序的强信号 - 最关键但常被忽略的一点:写入侧没变化。
innodb_rows_inserted、innodb_buffer_pool_reads不会因隐藏而降低——隐藏不减少 B+ 树维护开销。如果压测中 QPS 下降、CPU 升高、IO 暴涨,很可能是多个隐藏索引在后台默默拖慢写入
真正危险的不是“看不见”,而是“以为它没代价”——不可见索引照常吃 CPU、占内存、耗 IO,只是查询计划里不显示而已。观察窗口至少 24 小时,重点不是某条 SQL 变慢,而是 Handler 指标和慢查分布是否整体偏移。



















