参考文章
https://time.geekbang.org/column/article/79700
https://time.geekbang.org/column/article/80147
NLJ(Index Nested-Loop Join)
对于被驱动表有索引的情况
遍历驱动表,每读出一条驱动表上的数据,都会去被驱动表的索引树上获取满足条件的数据,组成一行作为结果集的一部分。然后重复上述步骤
NLJ优化使用MRR的时候,就会先讲驱动表的数据部分存放到join_buffer中,然后一次性传入一批的关联数据到被驱动表中,加快查询速度
假如驱动表的数据过多,也会有分段放入join_buffer的情况(BKA算法)
BNL(Block Nested-Loop Join)
对于被驱动表没有可用索引的情况
对驱动表做遍历,将数据放入join buffer,然后对第二张表做遍历,在内存中做匹配放入join buffer中
假如驱动表太大,join buffer不够的情况,会分块获取被驱动表的数据,然后逐块去做上述的步骤(被驱动表被扫描的次数增加)
这种情况就不适合使用join去做连表查询了
原因:假设被驱动表也非常大
-
被驱动表全表扫描次数增多,io增加
-
本身比较的次数也很多
-
对buffer pool 影响时间比较久,使业务正常访问的数据页没有机会进入young区
对于BNL的一种优化,mysql 8.0以后的hash join(个人理解:相较于BNL,减少了比较的次数)
http://mysql.taobao.org/monthly/2019/11/02/
使用到BNL的情况(这种情况就需要优化了)
image常说的小表驱动大表 何谓小表
应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”
网友评论