ALTER TABLE ... ALTER INDEX ... INVISIBLE 可瞬时停用索引,仅修改元数据、不锁表、不重建,但写入开销和唯一性校验仍存在;主键、外键依赖索引等不支持该操作,需查 INFORMATION_SCHEMA.STATISTICS.IS_VISIBLE 确认生效。

怎么用 ALTER TABLE ... ALTER INDEX ... INVISIBLE 瞬时停用索引
这不是删除,而是让优化器“假装看不见”——执行计划里不会出现它,但磁盘空间、写入开销、唯一性校验全在。操作本身只改元数据,毫秒级完成,不锁表、不重建、不影响业务。
-
ALTER TABLE orders ALTER INDEX idx_user_id INVISIBLE是唯一合法语法;SET INVISIBLE或MODIFY INDEX会直接报错ERROR 1064 - 主键(含隐式主键)、外键依赖的唯一索引、全文索引、空间索引不支持设为不可见,尝试会触发
ERROR 3522 - 执行后别只信
Query OK,立刻查INFORMATION_SCHEMA.STATISTICS.IS_VISIBLE,值为'NO'才算生效
为什么 EXPLAIN 不显示不可见索引,以及怎么让它“临时现身”
EXPLAIN 默认压根不把不可见索引纳入候选集,所以 key 字段为空或走别的索引,这正常。想对比“有/无该索引”的真实影响,必须手动打开开关:
- 会话级启用(推荐):
SET SESSION optimizer_switch = 'use_invisible_indexes=on',再跑EXPLAIN SELECT ... WHERE ... - 单条 SQL 启用(更安全):
SELECT /*+ SET_VAR(optimizer_switch = "use_invisible_indexes=on") */ * FROM orders WHERE status = 'shipped' - 注意:
FORCE INDEX(idx_name)会直接报错ERROR 1176 (42000): Key 'idx_name' doesn't exist,不是失效,是优化器已将其逻辑注销
压测时必须盯住的三个真实信号,而不是只看 EXPLAIN
单条 EXPLAIN 结果容易误判,真正影响性能的是线上负载。切换后至少观察 24 小时,覆盖完整业务周期:
- 查
performance_schema.table_io_waits_summary_by_index_usage,重点看COUNT_STAR是否归零——但注意:低频关键查询可能漏统计,不能当唯一依据 - 盯慢查询日志,特别是
Query_time突增、Rows_examined暴涨的语句 - 监控
Handler_read_next/Handler_read_rnd_next是否明显上升,这是全表扫描或回表激增的信号
回滚快,但应用层和备份链路容易踩坑
恢复只需一条 ALTER TABLE ... VISIBLE,秒级生效。但以下环节常被忽略,导致“以为回滚了,其实没真回”:
- 应用代码里写了
FORCE INDEX或USE INDEX—— 这些提示会直接失败,必须提前清理所有 ORM 配置和 SQL 注释 - 物理备份(如 xtrabackup)不保留可见性元数据,恢复后索引自动变回
VISIBLE;而mysqldump默认导出INVISIBLE属性,但 5.7 及更低版本解析会失败 - 分区表上对某个分区设为不可见,
ALTER TABLE ... REORGANIZE PARTITION可能重置所有分区索引状态,需事后复查
真实压测中,最常被低估的是写入开销——设成不可见后,INSERT/UPDATE/DELETE 依然照常维护该索引页,只是 SELECT 不走它。所以别指望靠这个降低写延迟或释放磁盘空间。它的价值只在一个地方:帮你确认“删掉它,到底会不会让某些查询崩掉”。



















