Mysql优化(出自官方文档) - 第三篇
1 Multi-Range Read Optimization(MRR)
当使用二级索引进行多范围查找的时候,往往会导致对磁盘大量的随机访问,这就导致了局部性非常差,因此,Mysql在遇到这种场景的时候,首先会利用二级索引查找出所有的唯一索引,然后进行排序,在进行访问,这样子,就能大大的减少随机访问,众所周知,对于传统机械硬盘,顺序读的效率比随机读的效率要高很多。
需要注意的是:
-
MRR优化不支持创建在virtual generated columns上的二级索引,InnoDB支持virtual generated columns -
如果
Mysql使用了这种优化,那么在EXPLAIN输出结果的Extra列会显示Using MRR -
如果查询的结果完全可以通过
index产生(covering index, 覆盖索引:指部分列信息存储在索引里面)那么将不会使用MRR,
2 Block Nested-Loop(BNL) and Batched Key Access Joins(BKA)
BKA算法可用于对joined table的索引访问和join buffer,BKA支持inner join, outer join, semijoin,以及nested outer join,BKA可以大大提高table scanning的性能。
-
Join Buffer Management for Block Nested-Loop and Batched Key Access Algorithms
在
Mysql中,Join buffer分为regular buffer和incremental buffer,regular可以理解为我们通常理解的buffer,incremental则是建立在regular的前提下,存储的部分列不是真正的数据,而是对上一个buffer的引用。假设有一个场景,三表join,t1 join t2 join t3,Mysql使用B1作为t1和t2的join临时结果,B2作为和t3的结果,那么通常来讲:B1是一个regular buffer,Mysql会把t1和t2的匹配结果存储在B1中,B1中只会存储匹配到的行,不会有任何多余的行,并且,如果某一列是NULL,Mysql也不会为该列分配任何空间。B2是一个incremental buffer,Mysql会把t3中匹配的行存入到B2中,然后再把B1中t1和t2的链接存储到B2中,这样子就避免了数据无意义的拷贝操作。
可以看到
incremental buffer不是独立的,一般来讲,需要多个buffer,第一个buffer往往是regular buffer,后面的buffer才是incremental buffer。 -
Block Nested-Loop Algorithm for Outer Joins and Semijoins
当前的
Mysql BNL算法已经支持outer join和semi join了,当join操作发生在join buffer上的时候,通过将row放到buffer里面会同时放入一个match flag,表示join的匹配情况。如果
Mysql使用了BNL,那么将会在EXPLAIN中体现如下,在Extra列,结果为:Using join buffer (Block Nested Loop), 在Type列,为:ALL,index, 或者range. -
Batched Key Access Joins
BKA通常用在有索引访问的第二个join上,在BNL join算法中,当第一个join使用join buffer产生了多个列,此时BKA会把第一个join结果的多个key批量发给MRR(第一节)接口,MRR engine会使用更优化的方式进行table scan,可以大大提升效率。在
EXPLAIN中,如果使用BKA,那么Extra列的结果为:Using join buffer (Batched Key Access),type列的结果为:reforeq_ref.