当前位置: 代码网 > it编程>数据库>Mysql > MySQL的联合索引范围条件失效问题解决办法

MySQL的联合索引范围条件失效问题解决办法

2026年04月23日 Mysql 我要评论
联合索引的排序逻辑:联合索引是多列组合的索引(如 idx(a, b, c)),其底层 b + 树的排序规则是:先按列 a 排序 → a 值相同的行,再按列 b 排序 → a 和 b

联合索引的排序逻辑:

  • 联合索引是多列组合的索引(如 idx(a, b, c)),其底层 b + 树的排序规则是:先按列 a 排序 → a 值相同的行,再按列 b 排序 → a 和 b 都相同的行,最后按列 c 排序。可以理解为:索引树是 “先按第一把钥匙排序,第一把相同再按第二把,以此类推”。

非等值的范围条件:

  • 常见操作符:>、<、between、like '%xx'(注意:in 是 “等值多值查询”,不算范围条件;>=、<= 虽属于范围,但本质是 “包含边界的 「 等值 」 延伸”,优化器更易利用)。

范围条件对索引的影响:

  • 联合索引的 “可用性” 依赖于 前缀列的有序性 —— 只有前一列是 “等值匹配” 时,后一列的索引排序才有意义。一旦某一列用了 “非等值范围条件”,其右侧所有列的索引排序会直接 “混乱”,优化器会放弃使用这些右侧列的索引部分。

举例

假设数据如下:

(name='张三', age=20, score=85)
(name='张三', age=20, score=90)
(name='张三', age=22, score=80)
(name='李四', age=19, score=95)
(name='李四', age=21, score=88)

情况一:

select * from student where name='张三' and age=20 and score=90;
  • 逻辑:先通过 name='张三'(等值)定位到前 3 行 → 再通过 age=20(等值)定位到前 2 行 → 最后通过 score=90(等值)精准命中目标行。
  • 结论:索引 idx(name, age, score) 全列有效。

情况二:

select * from student where name='张三' and age>20 and score=80;
  • 逻辑:name='张三'(等值)定位到前 3 行 → age>20(非等值范围条件)筛选出 age=22 的 1 行(此时,age>20 的部分中,score 没有有序性可言 —— 因为如果有更多数据,age=23score 可能是 70,age=24score 可能是 90,完全无序)。
  • 结论:score 列的索引失效,优化器只能用 nameage 的索引,score=80 需在筛选后的结果中 “逐行判断”(无法利用索引快速查找)。

情况三:

select * from student where name='张三' and age>20 and score=80;
  • 逻辑:同情况 2,age 是范围列,其右侧的 score 索引失效。

为辅助理解,这里补充说明:若查询条件为where name='张三' and age>=20,age>20的部分索引仍会失效,只有age=20的部分查找时可以用到索引。

总结

>=、<= 能保留 “前缀等值部分的有序性”,而 >、< 会破坏边界的等值连续性,导致索引选择性更差,甚至完全失效。尽量使用大于等于(>=)或小于等于(<=)。

注意事项补充

  1. 单列索引无此问题:只有联合索引才有 “左侧 / 右侧列” 的概念,单列索引无论用 >、< 还是 >=、<=,都能正常利用索引;
  2. in 不算非等值范围条件in 是 “等值多值查询”,比如 name in ('张三', '李四') and age=20age 仍能利用索引(因为 name 虽多值但仍是等值匹配,age 排序有效);
  3. 范围列尽量放联合索引右侧:设计联合索引时,若一定要用到非等值范围条件,应将用非等值范围条件的列放在最后,避免影响左侧列的索引可用性;
  4. 覆盖索引可缓解失效影响:如果查询的列都在联合索引中(如 select name, age, score from ...),即使右侧列失效,优化器仍会用 “索引全扫描”(无需回表),效率依然高于全表扫描。

联合索引中,什么时候索引是有效的,什么时候所以是无效的?

注意:是不是使用索引,和查询条件的顺序无关(优化器会自动调整条件的顺序),但和这些字段的查询手段有关

例子:建立了abc的联合索引,相当于建立了 a的单列索引,ab的联合索引,以及abc的联合索引

情况一:模糊查询生效失效的情况

一般根据最左匹配的原则,但在遇到范围查询后,匹配终止,也就是说,当条件为:

a like ‘%str%’ 或者 a like ‘%str’ 时,不走索引;

当条件为 a like ‘str%’ 或者 “>”, “<”, "between"时, 仅使用了联合索引中a的部分

b,c 同理,根据查询方式不同,即便条件中的3个字段都在索引里,也不一定使用了全索引

假如条件是 a = 1 and b = 2 and c = 3 这类情况,是必然走这个联合索引了

情况二:a% and b的情况

b不走索引但走索引下推(b走了索引下推,减少了回表次数。。。。。如果b没有索引下推,则还要在a%回表后进行一次b筛选)

b是不走索引的话:

首先a%会走索引的进行模糊查询,将模糊查询出来的主键进行回表(如果覆盖索引就不需要回表),回表后再根据b进行筛选,这时候b是不走索引的
b使用索引下推的话:

首先a%会走索引的进行模糊查询,模糊查询结束的时候,会将b条件索引下推到存储引擎层,这时候会从模糊查询的结果中筛选出来符合b的。最后再回表查询对应的字段(如果覆盖索引就不需要回表)。减少了回表的次数。

到此这篇关于mysql的联合索引范围条件失效问题解决办法的文章就介绍到这了,更多相关mysql联合索引范围条件失效内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com