一、join算法

mysql只支持一种join算法:nested-loop join(嵌套循环连接),但nested-loop join有三种变种。

simple nested-loop join

如图,r为驱动表,s为匹配表,可以看到从r中分别取出r1、r2、…..rn去匹配 s 表的左右列,然后再合并数据,对s表进行了 r*n 次遍历(极端情况下),对数据库开销大
image.png

index nested-loop join(索引嵌套)

这个要求非驱动表上有索引,可以通过索引来加速查询;查找驱动表的所有数据,然后根据索引去非驱动表查找,如果关联字段是主键,则只需查找 n 次,如果是非主键的话,需要再次回表查询出所有字段。性能比主键查找要慢
image.png

block nested-loop join

如果有索引,会选取第二种方式进行join,但如果join列没有索引,就会采用block nest-loop join;可以看出中间有个join buffer缓冲区,是将驱动表的所有join相关的列都先缓存到join buffer中,然后批量去非驱动表进行匹配,实质就是将多次比较合并成一次,降低了非驱动表的访问频率。
默认情况下join_buffer_size = 256k, 再查找的时候mysql会将所有需要的列缓存到join buffer中,包括select的列,而不仅仅只缓存关联列,如果join buffer size大小不足,则会分段放
image.png

二、inner、left、right的区别

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

优化建议:
join不超过三张表
小表驱动大表
关联字段最好是主键索引,或是查询时使用覆盖索引