> MySQL 的连表查询我们经常使用,合理的使用连表查询会大大提升查询速度。MySQL使用的是一种叫做嵌套循环连接。

- 驱动表

left join 的左表,通常扫描的次数都是1

- 被驱动表

left join 的右表, 根据算法不同扫描次数不同

# 一、simple nested-loop join(SNLJ)

- 从驱动表中取第一条记录,和被驱动表的所有记录比较判断。

- 从驱动表中取第二条记录,和被驱动表的所有记录比较判断。

- 直到驱动表的所有记录都和被驱动表的所有记录都比较完毕。

- 比较次数是 M*N

# 二、index nested-loop join(INLJ)

- 通常,被驱动表建有索引,此时驱动表中的每一条记录通过被驱动表的索引进行访问。

- 因为索引查询的成本是比较固定的,故MySQL优化器都倾向于使用记录数少的表作为驱动表。

- 驱动表会根据被驱动表关联字段的索引进行查找,当在索引上找到了符合的值,再回表(被驱动表)进行查询,也就是只有当匹配到索引以后才会进行回表。

- 比较次数M*index(N)

# 三、block nested-loop join(BNLJ)

- 通常情况下,mysql会先判断被驱动表是否有索引,如果没有索引则使用BNLJ。

- 相较于SNLJ,BNLJ的改进就在于可以减少内表(被驱动表)的扫描次数,仅需扫描一次。

- BNLJ多了一个中间处理过程,也就是join buffer,使用join buffer将驱动表的查询JOIN相关列都给缓冲到了JOIN BUFFER当中,然后批量与被驱动表进行比较,可以将多次比较合并到一次,降低了被驱动表的访问频率。

- 在MySQL当中,我们可以通过参数join_buffer_size来设置join buffer的值,然后再进行操作,默认情况下join_buffer_size=256K。

- 在查找的时候MySQL会将所有需要的列缓存到join buffer当中,包括select的列,而不是仅仅只缓存关联列。

- 在一个有N个JOIN关联的SQL当中会在执行时候分配N-1个join buffer。

# 四、使用场景

- 1、如果使用left join语句,则left join 前的表设置为驱动表,left join 后的表设置为被驱动表,被驱动表如果没加索引,效率会非常低

- 2、使用inner join 连接表语句,则mysql会自动优化, 将加索引的表设置为被驱动表,未加索引的表设为驱动表

- 3、两个表都存在索引的情况下,小表驱动大表查询效果更好