MySQL中Visible INDEX与Invisible INDEX是什么?该如何选型?
MySQL 可见索引与不可见索引相关问题解答
1. 两类索引的定义与优劣对比
- Visible INDEX(可见索引):MySQL 默认的索引形态,查询优化器生成执行计划时会正常识别、匹配这类索引,索引创建后会随表数据的增删改操作实时更新维护,是常规业务场景下的标准索引类型。
- Invisible INDEX(不可见索引):MySQL 8.0 版本推出的索引特性,索引本身的存储结构、数据一致性维护逻辑、占用的存储空间和同定义的可见索引完全一致,唯一区别是查询优化器默认不会在执行计划中选用这类索引。
两类索引不存在绝对的“谁更优”:
二者的维护成本、查询加速能力没有本质差异,仅在「优化器是否默认调用」这一行为上有区别。需要索引直接承接线上查询流量时选可见索引;需要做索引上线验证、冗余索引下线前置校验时,不可见索引的特性更适配。
2. 100万行级无索引表的索引选型建议
100万行数据属于中小规模表,建索引的锁等待、执行耗时都在可控区间,按以下流程操作风险最低、收益最高:
- 先梳理所有待优化查询的过滤、排序、分组字段,确定需要创建的索引字段、联合索引字段顺序,不要盲目给所有字段加索引。
- 所有待上线的索引优先创建为不可见索引,避免建错索引(比如联合索引顺序错误、字段选择偏差)直接干扰线上正常执行计划,创建示例:
-- 以订单表的user_id、create_time联合索引为例 CREATE INDEX idx_order_uid_ct ON orders(user_id, create_time) INVISIBLE;
- 索引创建完成后,开启当前会话的不可见索引识别开关,逐条验证目标查询的执行计划,确认索引命中效果、扫描行数符合预期,该操作仅对当前会话生效,不会影响线上业务:
SET SESSION optimizer_switch='use_invisible_indexes=on'; -- 用EXPLAIN校验执行计划 EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND create_time > '2024-01-01';
- 所有索引验证通过后,逐个将索引修改为可见状态,逐步承接线上查询流量:
ALTER TABLE orders ALTER INDEX idx_order_uid_ct VISIBLE;
- 后续如果要清理疑似冗余的索引,不要直接执行DROP操作,先把目标索引修改为不可见状态观察1-2个业务周期,确认没有查询性能异常、业务报错后再彻底删除,避免误删核心索引导致故障。
内容的提问来源于stack exchange,提问作者Crazy Developer
相关产品推荐
相关产品推荐

