mysql指引(五):join关联查询底层原理(下)

前言

mysql指引(四):join关联查询底层原理(上) 中,研究了 NLJ,BNL和带有索引的嵌套循环连接。本篇,我们就来看看 Multi-Range Read Optimization 优化和 Batched Key Access 连接。有了上篇的基础,本篇理解起来会更清晰。

索引的简单结构

在解读之前,有必要稍微了解一下数据的读取方式。

对于走主键索引的,则如下图:

直接走搜索树,从而找到某个数据,比如 ID2这个节点,其存储 ID2和对应的本行数据内容(暂时这样理解)。

如果走的是普通索引,则过程如下:

首先根据普通索引去右边搜索树找到对应的主键ID2,然后再去左侧的主键索引搜索树去查找ID2的数据。去主键搜索树查找的过程又叫做 回表 操作。

目前,知道这样就足够了,对于索引的进一步学习,会在后续文章中涉及。

Multi-Range Read Optimization

主键索引搜索树中查找数据时,考虑如下情景:假如主键ID是自增的,然后我们希望查找的是 1,330,5,6,800 这几个主键的数据。那么我们可以按照 800,330,5,6,1这样的顺序依次去查找,也可以按照1,5,6,330,800这样的顺序查找。二者查找的性能相同吗?


答案是不同的。因为第一种方式磁盘基本都是随机访问的,磁盘随机访问的性能是不如顺序访问的。而第二种方式则尽可能让磁盘进行顺序查找,所以性能也会高一点。

既然这样,明明主键是有序递增的,为什么还会出现查找主键索引时传入的主键ID不是按递增顺序查找的呢?

原因在于,当基于普通索引查询时,顺序是按照普通索引的顺序来的,那就很有可能再回表的过程中不是按照主键顺序去读取数据,造成随机读现象,拖累性能。

那我们怎么解决呢?这就需要MRR优化。

MRR的工作原理如下:

MRR enables data rows to be accessed sequentially rather than in random order, based on index tuples. The server obtains a set of index tuples that satisfy the query conditions, sorts them according to data row ID order, and uses the sorted tuples to retrieve data rows in order. This makes data access more efficient and less expensive.

也就是 MRR 会根据索引将 row ID 即主键值缓存起来,然后将他们按照主键值进行排序,最后依次拿出主键值执行回表操作。

  1. A portion of the index tuples are accumulated in a buffer.
  2. The tuples in the buffer are sorted by their data row ID.
  3. Data rows are accessed according to the sorted index tuple sequence.

注意,查找的数量越多,越能体现MRR的顺序IO的优势。

Batched Key Access Join

In MySQL, a Batched Key Access (BKA) Join algorithm is available that uses both index access to the joined table and a join buffer.

两个关键词:

  • index access,实际上结合了MRR
  • join buffer

实现原理是什么呢?我们来看两幅图,第一幅是MRR的处理结构:

MRR的原理不需要赘述了最终是按照主键ID的顺序执行数据的查找,那么BKA处理结构呢?

不同点在于会首先将表 T1 的数据读入到 join buffer 中,这样就可以从 join buffer 中将数据批量的传递给 MRR,从而利用到MRR的顺序读优势,之后和其他关联一样,执行数据嵌套匹配即可。

最后,来看一下BKA的特性:

  • The BKA algorithm supports inner join, outer join, and semijoin operations, including nested outer joins. 可以看到支持多种连接
  • improved join performance due to more efficient table scanning. 提升了数据表的扫描性能
  • the Block Nested-Loop (BNL) Join algorithm previously used only for inner joins is extended and can be employed for outer join and semijoin operations, including nested outer joins. 可以将前文的BNL算法变成BKA算法,当然只需要在被驱动表加入索引即可。

实际上对于这些关联实现原理还有很多需要研究,此处先留好映像。后面再回过头深入即可 。

索引已经绕不开了,下面的文章,我们就来学习研究索引的底层原理。

发布了44 篇原创文章 · 获赞 85 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zhou307/article/details/104172743