MySQL Join的底层实现原理

mysql只支持一种join算法:Nested-Loop Join(嵌套循环链接),但Nested-Loop Join有三种变种:Simple Nested-Loop Join,Index Nested-Loop Join,Block Nested-Loop Join
(注:参考公众号:InsideMySQL)mysql


原理:

1.Simple Nested-Loop Join:

以下图,r为驱动表,s为匹配表,能够看到从r中分别取出r一、r二、......、rn去匹配s表的左右列,而后再合并数据,对s表进行了rn次访问,对数据库开销大web


webp

微信截图_20181122171451.png算法

2.Index Nested-Loop Join(索引嵌套):

这个要求非驱动表(匹配表s)上有索引,能够经过索引来减小比较,加速查询。
在查询时,驱动表(r)会根据关联字段的索引进行查找,挡在索引上找到符合的值,再回表进行查询,也就是只有当匹配到索引之后才会进行回表查询。
若是非驱动表(s)的关联健是主键的话,性能会很是高,若是不是主键,要进行屡次回表查询,先关联索引,而后根据二级索引的主键ID进行回表操做,性能上比索引是主键要慢。sql


webp

微信截图_20181122171515.png数据库

3.Block Nested-Loop Join:

若是有索引,会选取第二种方式进行join,但若是join列没有索引,就会采用Block Nested-Loop Join。能够看到中间有个join buffer缓冲区,是将驱动表的全部join相关的列都先缓存到join buffer中,而后批量与匹配表进行匹配,将第一种屡次比较合并为一次,下降了非驱动表(s)的访问频率。默认状况下join_buffer_size=256K,在查找的时候MySQL会将全部的须要的列缓存到join buffer当中,包括select的列,而不是仅仅只缓存关联列。在一个有N个JOIN关联的SQL当中会在执行时候分配N-1个join buffer。缓存


webp

微信截图_20181122171528.png微信


实例:

假设两张表a 和 b:ide

a结构:
comments_id        bigInt(20)    P
for_comments_if    mediumint(9)product_id         int(11)order_id           int(11)...

b结构:
id            int(11)       p
comments_id   bigInt(20)product_id    int(11)...

其中b的关联有comments_id,因此有索引。oop

join:

SELECT * FROM a gc
JOIN b gcf ON gc.comments_id=gcf.comments_id
WHERE gc.comments_id =2056

使用的是Index Nested-Loop Join,先对驱动表a的主键筛选,获得一条,而后对非驱动表b的索引进行seek匹配,预计获得一条数据。性能

下面这种状况没用到索引:

SELECT * FROM a gc
JOIN b gcf ON gc.order_id=gcf.product_id

使用Block Nested-Loop Join,若是b表数据少,做为驱动表,将b的须要的数据缓存到join buffer中,批量对a表扫描

left join:

SELECT * FROM a gc
LEFT JOIN b gcf ON gc.comments_id=gcf.comments_id

这里用到了索引,因此会采用Index Nested-Loop Join,由于没有筛选条件,会选择一张表做为驱动表去进行join,去关联非驱动表的索引。

若是加了条件:

SELECT * FROM b gcf
LEFT JOIN a gc ON gc.comments_id=gcf.comments_id
WHERE gcf.comments_id =2056

就会从驱动表筛选出一条来进行对非驱动表的匹配。


left join:会保全左表数据,若是右表没相关数据,会显示null
fight join:会保全右表数据,若是左表没相关数据,会显示null
inner join:部分主从表,结果会取两个表针对on条件相匹配的最小集

连接:https://www.jianshu.com/p/16ad9669d8a9

相关文章
相关标签/搜索