2. 关联查询优化
结论1:对于内连接来说,查询优化器可以决定谁来作为驱动表,谁作为被驱动表出现
结论2:对于内连接来讲,如果表的连接条件中只能有一个字段有索引,则有索引的字段所在的表会被作为被驱动表
结论3:对于内连接来说,在两个表的连接条件都存在索引的情况下,会选择小表作为驱动表。小表驱动大表
2.1 Index Nested-Loop Join(索引嵌套循环连接)
Index Nested-Loop Join其优化的思路主要是为了减少内层表数据的匹配次数,所以要求被驱动表上必须有索引才行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cr395amv-1661608724710)(https://cdn.jsdelivr.net/gh/aoshihuankong/cloudimg@master/img/202204011826671.png)]
2.2 Block Nested-Loop Join(块嵌套循环连接)
如果存在索引,那么会使用index的方式进行join,如果join的列没有索引,被驱动表要扫描的次数太多了。每次访问被驱动表,其表中的记录都会被加载到内存中,然后再从驱动表中取一条与其匹配,匹配结束后清除内存,然后再从驱动表中加载一条记录,然后把被驱动表的记录再加载到内存匹配,这样周而复始,大大增加了IO的次数。为了减少被驱动表的IO次数,就出现了Block Nested-Loop Join的方式。
不再是逐条获取驱动表的数据,而是一块一块的获取,引入了join buffer缓冲区,将驱动表join相关的部分数据列(大小受join buffer的限制)缓存到join buffer中,然后全表扫描被驱动表,被驱动表的每一条记录一次性和join buffer中的所有驱动表记录进行匹配(内存中操作),将简单嵌套循环中的多次比较合并成一次,降低了被驱动表的访问频率。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FCIhBdvX-1661608724711)(https://cdn.jsdelivr.net/gh/aoshihuankong/cloudimg@master/img/202204011833000.png)]
2.3 Hash Join
从MySQL的8.0.20版本开始将废弃BNLJ,因为从MySQL8.0.18版本开始就加入了hash join默认都会使用hash join**
Nested Loop:对于被连接的数据子集较小的情况下,Nested Loop是个较好的选择。
Hash Join是做大数据集连接时的常用方式,优化器使用两个表中较小(相对较小)的表利用Join Key在内存中建立散列值,然后扫描较大的表并探测散列值,找出与Hash表匹配的行。
这种方式适用于较小的表完全可以放入内存中的情况,这样总成本就是访问两个表的成本之和。
在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要求有较大的临时段从而尽量提高I/O的性能。
它能够很好的工作于没有索引的大表和并行查询的环境中,并提供最好的性能。Hash Join只能应用于等值连接,这是由Hash的特点决定的。
评论

