Mysql必知必会之索引下推和索引合并

索引下推

假设现在对表建立了一个name和age的联合索引,为了方便理解,我把前面的图再拿过来

接下来要执行如下的sql

select * from `user` where name > '王五' and age > 22;

在MySQL5.6(不包括5.6)之前,整个sql大致执行步骤如下:

  • 先根据二分查找,定位到name > '王五'的第一条数据,也就是id=4的那个赵六
  • 之后就会根据id=4进行回表操作,到聚簇索引中查找id=4其它字段的数据,然后判断数据中的age是否大于22,是的话就说明是我们需要查找的数据,否则就不是
  • 之后顺着链表,继续遍历,然后找到一条记录就回一次表,然后判断age,如此反复下去,直至结束

所以对于图上所示,整个搜索过程会经历5次回表操作,两个赵六,两个刘七,一个王九,最后符合条件的也就是id=6的赵六那条数据,其余age不符和。虽然这么执行没什么问题,但是不知有没有发现其实没必要进行那么多次回表,因为光从上面的索引图示就可以看出,符合name > '王五' and age > 22的数据就id=6的赵六那条数据。所以在MySQL5.6之后,对上面的age > 22判断逻辑进行了优化。前面还是一样,定位查找到id=4的那个赵六,之后就不回表来判断age了,因为索引列有age的值了,那么直接根据索引中age判断是否大于22,如果大于的话,再回表查询剩余的字段数据(因为是select *),然后再顺序链表遍历,直至结束。所以这样优化之后,回表次数就成1了,相比于前面的5次,大大减少了回表的次数。而这个优化,就被称为索引下推,就是为了减少回表的次数。

索引合并

索引合并(index merge)是从MySQL5.1开始引入的索引优化机制,在之前的MySQL版本中,一条sql多个查询条件只能使用一个索引,但是引入了索引合并机制之后,MySQL在某些特殊的情况下会扫描多个索引,然后将扫描结果进行合并。结果合并会为下面三种情况:

  • 取交集(intersect)
  • 取并集(union)
  • 排序后取并集(sort-union)

为了不耽误演示,删除之前所有的索引,然后为name和age各自分别创建一个二级索引idx_name和idx_age

取交集(intersect)

当执行下面这条sql就会出现取交集的情况

select * from `user` where name = '赵六' and age= 22;

查看执行计划

type是index_merge,并且possible_key和key都是idx_nameidx_age,说明使用了索引合并,并且Extra有Using intersect(idx_age,idx_name),intersect就是交集的意思。整个过程大致是这样的,分别根据idx_nameidx_age取出对应的主键id,之后将主键id取交集,那么这部分交集的id一定同时满足查询name = '赵六' and age= 22的查询条件(仔细想想),之后再根据交集的id回表。不过要想使用取交集的联合索引,需要满足各自索引查出来的主键id是排好序的,这是为了方便可以快速的取交集。比如下面这条sql就无法使用联合索引

select * from `user` where name = '赵六' and age > 22;

只能用name这个索引,因为age > 22查出来的id是无序的,前面在讲索引的时候有说过索引列的排序规则。由此可以看出,使用联合索引条件还是比较苛刻的。

取并集(union)

取并集就是将前面例子中的and换成or

select * from `user` where name = '赵六' or age = 22;

前面执行的情况都一样,根据条件到各自的索引上去查,之后对查询的id取并集去重,之后再回表。同样地,取并集也要求各自索引查出来的主键id是排好序的,如果查询条件换成age > 22时就无法使用取并集的索引合并

select * from `user` where name = '赵六' or age > 22;

排序后取并集(sort-union)

虽然取并集要求各自索引查出来的主键id是排好序的,但是如果遇到没排好序的情况,mysql会自动对这种情况进行优化,会先对主键id排序,然后再取并集,这种情况就叫 排序后取并集(sort-union)。比如上面提到的无法直接取并集的sql就符合排序后取并集(sort-union)这种情况

select * from `user` where name = '赵六' or age > 22;

原文来自于三友的java日记 

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/131030863