MySQL之索引深度探究(下)

覆盖索引

假设需要执行一条语句:

select * from T where k between 3 and 5;

最初对列k建立了索引,表中的数据呈现如下状态:

MySQL之索引深度探究(下)

其执行过程为:

  • 在k索引树上找到k值为3的记录,获取到ID=300;
  • 前往ID索引树中查找ID=300对应的记录。
  • 在k索引树上找到下一个符合k在3到5之间的记录,得到ID=500;
  • 再到ID索引树里查找ID=500对应的记录。
  • 在k索引树上找到下一个值为6的记录,发现不满足既定条件。

此过程中发生了回表操作。倘若建立的索引能够“覆盖”我们的查询需求,那就无需进行回表,这样的索引被称作覆盖索引。比如在上述查询语句中,若查询的是列k而非全部字段*,便是一个覆盖索引的情形。

需要注意的是,在引擎内部运用覆盖索引时,在索引k上实际能读取到R3 - R5这三个记录,但由于Server层只会从引擎处获取两条记录,所以MySQL将扫描行数判定为2。

最左前缀原则

B+树这种索引结构,能够凭借索引的最左前缀来定位记录。

例如建立了(name,age)的联合索引:

MySQL之索引深度探究(下)

当要查询name="张三"时,能够快速定位到ID4,然后往后进行遍历。

当要查询where name like "张%"时,也能够利用该索引,定位到ID3,接着往后遍历。

所以,索引的最左前缀可以是联合索引的最左边的N个字段,也可以是字符串索引的最左边的M个字符。

索引下推

还是假设建立了(name,age)的联合索引,现在有一条SQL语句如下:

select * from tuser where name like '张%' and age=10 and ismale=1;

依据最左前缀原则,这条语句能够利用name的索引。

对于其他条件的判断:

  • 在MySQL 5.6之前,只能从找到的第一个记录ID3开始逐个进行回表操作,到主键索引中找出数据行,再对比后面的两个字段。
  • MySQL 5.6引入了索引下推优化,能够在索引遍历过程中,先对索引中包含的字段进行判断,直接过滤掉不满足条件的记录,以此减少回表次数。

两者的对比情况如下,第一张图是没有索引下推的状况,第二张图是有索引下推的状况,箭头表示回表的走向:

MySQL之索引深度探究(下) MySQL之索引深度探究(下)
版权声明:程序员胖胖胖虎阿 发表于 2025年8月5日 下午10:07。
转载请注明:MySQL之索引深度探究(下) | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...