Mysql优化(出自官方文档) - 第三篇
Mysql优化(出自官方文档) - 第三篇
1 Multi-Range Read Optimization(MRR)
针对的对象是二级索引,当使用二级索引进行多范围查找的时候,往往会导致对磁盘大量的随机访问,这就导致了局部性非常差,因此,Mysql在遇到这种场景的时候,首先会利用二级索引查找出所有的唯一索引,然后进行排序(按照rowID的方式),再进行访问,这样子,就能大大的减少随机访问,众所周知,对于传统机械硬盘,顺序读的效率比随机读的效率要高很多。具体处理流程如下:
- 将查询得到的二级索引键值存放在一个缓存中,这时缓存中的数据是根据二级索引键值排序的
- 将缓存中的键值根据
RowID
进行排序 - 根据
RowID
的排序顺序来访问实际的数据文件(相当于将随机读转换为顺序读,提高读取效率)
需要注意的是:
-
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
列的结果为:ref
oreq_ref
.