优化器选错索引?MySQL 隐藏索引调试 + 避坑实战

0 阅读2分钟

MySQL 隐藏索引

  • 一、定义
  • 二、核心操作
  • 三、为什么需要隐藏索引?
  • 四、避坑

一、定义

隐藏索引是一个 “待命” 的索引,平时不参与查询优化,但随时可以切换回来。

  • “待命”因为物理存在:索引真实存在于磁盘上,并且会随着数据的增删改而实时更新。
  • “不参与”因为逻辑不可见:对查询优化器来说,它就像不存在一样,优化器不会考虑使用它,即使你用 FORCE INDEX 也不行。

二、核心操作

1、创建隐藏索引

-- 直接在 CREATE INDEX 语句末尾加上 INVISIBLE 即可。
CREATE INDEX idx_last_name ON customer(last_name) INVISIBLE;

2、修改现有索引的可见性

-- 隐藏索引
ALTER TABLE customer ALTER INDEX idx_last_name INVISIBLE;
​
-- 恢复可见
ALTER TABLE customer ALTER INDEX idx_last_name VISIBLE;

3 、强制优化器使用隐藏索引(测试使用)

默认情况下,优化器完全忽略隐藏索引。但可以通过系统变量在当前会话中临时改变这个行为:

-- 查看当前设置
SELECT @@optimizer_switch;
​
-- 在当前会话中,允许优化器使用隐藏索引
SET SESSION optimizer_switch="use_invisible_indexes=on";

三、为什么需要隐藏索引?

其作用在于安全地测试和管理索引

场景一:安全删除索引

在生产环境中,删除一个索引风险很高,你不确定删除后会不会影响性能。

  • 先把索引设为 INVISIBLE,观察一段时间。如果性能没有下降,再放心删除;如果出问题,立刻设回 VISIBLE,无需重建。

场景二:测试新索引

当你想测试一个新索引的效果时:

  1. 创建一个 INVISIBLE 的新索引。
  2. 在测试会话中,通过 optimizer_switch 打开隐藏索引开关,验证性能提升。
  3. 验证通过后,再将其设为 VISIBLE 正式使用。

场景三:优化器调试

当你怀疑某个索引导致优化器做出了错误选择时,可以将其隐藏,观察执行计划的变化,从而定位问题。

四、避坑

  1. 主键不能隐藏:主键索引是聚簇索引,是数据组织的核心,因此不能被设置为隐藏。
  2. 维护开销依然存在:即使索引是隐藏的,它依然会占用磁盘空间,并且在写入(INSERT/UPDATE/DELETE)时需要维护,所以不要滥用。
  3. FORCE INDEX 无效:即使你强制使用隐藏索引,优化器也会忽略它,除非你打开了 use_invisible_indexes 开关。