shanxiaoshuai
2020-08-29 18:44
采纳率: 66.7%
浏览 843

mysql复合索引中,使用like'xxx%'为什么不会使后续索引失效

最近在看索引优化相关的内容,有个知识点让我很疑惑。

举个例子:

create index index_c1c2c3 on table1(c1,c2,c3)

在表table1的c1,c2,c3三个字段创建复合索引,这个时候执行两条sql语句

1、select * from table1 where c1=a and c2>b and c3=c;

对该语句来说,因为c2列用了范围查询,导致复合索引只用了c1、c2两个字段,c3没用到。基于B+树的数据结构的话我觉得是没有问题。

2、select * from table1 where c1=a and c2 like 'c%' and c3=c;

对该语句来说,反而是三个索引都用到了,但是like的效果不是和范围查询一样吗?反正反B+树的数据结构来思考我是理解不了。各位大佬能帮忙解释一下吗?还是优化器在其中起作用了?

具体的实例如下,按B+树的结构来说,使用c2使用like后因为是范围查询,c3应该是无序的,怎么用索引呢?

图片

图片说明

图片说明

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • 新用户1 2021-03-27 13:48
    已采纳

    like KK%其实就是用到了索引下推优化

    对于辅助的联合索引(name,age,position),正常情况按照最左前缀原则,SELECT * FROM employees WHERE name like 'LiLei%' AND age = 22 AND position ='manager' 这种情况只会走name字段索引,因为根据name字段过滤完,得到的索引行里的age和position是无序的,无法很好的利用索引。

    在MySQL5.6之前的版本,这个查询只能在联合索引里匹配到名字是 'LiLei' 开头的索引,然后拿这些索引对应的主键逐个回表,到主键索引上找出相应的记录,再比对ageposition这两个字段的值是否符合。

    MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,可以有效的减少回表次数。使用了索引下推优化后,上面那个查询在联合索引里匹配到名字是 'LiLei' 开头的索引之后,同时还会在索引里过滤ageposition这两个字段,拿着过滤完剩下的索引对应的主键id再回表查整行数据。

    索引下推会减少回表次数,对于innodb引擎的表索引下推只能用于二级索引,innodb的主键索引(聚簇索引)树叶子节点上保存的是全行数据,所以这个时候索引下推并不会起到减少查询全行数据的效果。

    为什么范围查找Mysql没有用索引下推优化?

    估计应该是Mysql认为范围查找过滤的结果集过大,like KK% 在绝大多数情况来看,过滤后的结果集比较小,所以这里Mysql选择给 like KK% 用了索引下推优化,当然这也不是绝对的,有时like KK% 也不一定就会走索引下推 ,具体还要看MySQL分析各个索引使用成本,找出最优访问路径

    打赏 评论
  • 打赏 评论
  • 农夫丶果园 2020-08-31 17:50

    MYSQL中B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录 ; 只要满足最左前缀,就可以利用上索引。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符 ;
    你的联合索引是c1 , c2 , c3 , 你的where条件中包含了c1 , c2 , c3 , 所以按照最左N个字段来看以及 c2 字段最左M个字符来看 , 可以用到c1 , c2 , c3 的索引 ; 如果你把 c2 的搜索条件改成 like '%c' 结果就不一样了

    打赏 评论

相关推荐 更多相似问题