嵌套循环连接(Nested Loop Join)

循环嵌套连接是最基本的连接,正如其名所示那样,需要进行循环嵌套,嵌套循环是三种方式中唯一支持不等式连接的方式,这种连接方式的过程可以简单的用下图展示:

图1.循环嵌套连接的第一步

图2.循环嵌套连接的第二步

由上面两个图不难看出,循环嵌套连接查找内部循环表的次数等于外部循环的行数,当外部循环没有更多的行时,循环嵌套结束。另外,还
可以看出,这种连接方式需要内部循环的表有序(也就是有索引),并且外部循环表的行数要小于内部循环的行数,否则查询分析器就更倾向于Hash
Join(会在本文后面讲到)。

通过嵌套循环连接也可以看出,随着数据量的增长这种方式对性能的消耗将呈现出指数级别的增长,所以数据量到一定程度时,查询分析器往往就会采用这种方式。

合并连接(Merge Join)

Merge Join其实上就是将两个有序队列进行连接,需要两端都已经有序,所以不必像Loop Join那样不断的查找循环内部的表。其次,Merge Join需要表连接条件中至少有一个等号查询分析器才会去选择Merge Join。

Merge Join的过程我们可以简单用下面图进行描述:

图8.Merge Join第一步

Merge Join首先从两个输入集合中各取第一行,如果匹配,则返回匹配行。加入两行不匹配,则有较小值的输入集合+1,如图9所示。

.更小值的输入集合向下进1

因此,通常来说Merge
Join如果输入两端有序,则Merge Join效率会非常高,但是如果需要使用显式Sort来保证有序实现Merge Join的话,那么Hash
Join将会是效率更高的选择。但是也有一种例外,那就是查询中存在order by,group
by,distinct等可能导致查询分析器不得不进行显式排序,那么对于查询分析器来说,反正都已经进行显式Sort了,何不一石二鸟的直接利用
Sort后的结果进行成本更小的MERGE JOIN?在这种情况下,Merge Join将会是更好的选择。

另外,我们可以由Merge Join的原理看出,当连接条件为不等式(但不包括!=),比如说> < >=等方式时,Merge Join有着更好的效率。

哈希匹配(Hash Join)

哈希匹配连接相对前面两种方式更加复杂一些,但是哈希匹配对于大量数据,并且无序的情况下性能均好于Merge Join和Loop Join。对于连接列没有排序的情况下(也就是没有索引),查询分析器会倾向于使用Hash Join。

哈希匹配分为两个阶段,分别为生成和探测阶段,首先是生成阶段,第一阶段生成阶段具体的过程可以如图12所示。

图12.哈希匹配的第一阶段


12中,将输入源中的每一个条目经过散列函数的计算都放到不同的Hash Bucket中,其中Hash Function的选择和Hash
Bucket的数量都是黑盒,微软并没有公布具体的算法,但我相信已经是非常好的算法了。另外在Hash
Bucket之内的条目是无序的。通常来讲,查询优化器都会使用连接两端中比较小的哪个输入集来作为第一阶段的输入源。

接下来是探测阶段,对于另一个输入集合,同样针对每一行进行散列函数,确定其所应在的Hash Bucket,在针对这行和对应Hash Bucket中的每一行进行匹配,如果匹配则返回对应的行。


过了解哈希匹配的原理不难看出,哈希匹配涉及到散列函数,所以对CPU的消耗会非常高,此外,在Hash
Bucket中的行是无序的,所以输出结果也是无序的。

 

上面的情况都是内存可以容纳下生成阶段所需的内存,如果内存吃紧,则还会涉及到Grace哈希匹配和递归哈希匹配,这就可能会用到TempDB从而吃掉大量的IO。这里就不细说了,有兴趣的同学可以移步:http://msdn.microsoft.com/zh-cn/library/aa178403(v=SQL.80).aspx

总结

下面我们通过一个表格简单总结这几种连接方式的消耗和使用场景:

 

嵌套循环连接

合并连接

哈希连接

适用场景

外层循环小,内存循环条件列有序

输入两端都有序

数据量大,且没有索引

CPU

低(如果没有显式排序)

内存

低(如果没有显式排序)

IO

可能高可能低

可能高可能低

参考文献:

http://msdn.microsoft.com/zh-cn/library/aa178403(v=SQL.80).aspx

http://www.dbsophic.com/SQL-Server-Articles/physical-join-operators-merge-operator.html

以下博客做了一些三种join的耗时实验,可以参考分析:

http://www.jasongj.com/2015/03/07/Join1/

join中级篇---------hash join & merge join & nested loop Join的更多相关文章

  1. Merge join、Hash join、Nested loop join对比分析

    简介 我们所常见的表与表之间的Inner Join,Outer Join都会被执行引擎根据所选的列,数据上是否有索引,所选数据的选择性转化为Loop Join,Merge Join,Hash Join ...

  2. 浅谈SQL Server中的三种物理连接操作(Nested Loop Join、Merge Join、Hash Join)

    简介 在SQL Server中,我们所常见的表与表之间的Inner Join,Outer Join都会被执行引擎根据所选的列,数据上是否有索引,所选数据的选择性转化为Loop Join,Merge J ...

  3. 三大表连接方式详解之Nested loop join和 Sort merge join

    在早期版本,Oracle提供的是nested-loop join,两表连接就相当于二重循环,假定两表分别有m行和n行       如果内循环是全表扫描,时间复杂度就是O(m*n)       如果内循 ...

  4. Oracle 表的连接方式(1)-----Nested loop join和 Sort merge join

    关系数据库技术的精髓就是通过关系表进行规范化的数据存储,并通过各种表连接技术和各种类型的索引技术来进行信息的检索和处理. 表的三种关联方式: nested loop:从A表抽一条记录,遍历B表查找匹配 ...

  5. SQL Server nested loop join 效率试验

    从很多网页上都看到,SQL Server有三种Join的算法, nested loop join, merge join, hash join. 其中最常用的就是nested loop join. 在 ...

  6. 禁用nested loop join里的spool

    禁用nested loop join里的spool 转载自: https://blogs.msdn.microsoft.com/psssql/2015/12/15/spool-operator-and ...

  7. 1122MySQL性能优化之 Nested Loop Join和Block Nested-Loop Join(BNL)

    转自http://blog.itpub.net/22664653/viewspace-1692317/ 一 介绍  相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说 ...

  8. 44 答疑(三)--join的写法/Simple nested loop join的性能问题/Distinct和group by的性能/备库自增主键问题

    44 答疑(三) Join的写法 35节介绍了join执行顺序,加了straight_join,两个问题: --1 如果用left join,左边的表一定是驱动表吗 --2 如果两个表的join包含多 ...

  9. oracle多表连接方式Hash Join Nested Loop Join Merge Join

    在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式:        嵌套循环(Nested  Loops (NL) ...

随机推荐

  1. ios6.0 siri语音识别

    Siri 让你能够利用语音来完成发送信息.安排会议.拨打电话等更多事务* .只需像平常一样讲话,就能让 Siri 帮你做事.你会发现 Siri 是如此易用而且能干,精彩用法越用你会发现越多. 懂你所说 ...

  2. 【redis】redis实现API接口调用调用次数的限制

    redis实现API接口调用调用次数的限制 参考地址:https://bbs.csdn.net/topics/391856106?page=1 参考地址:https://www.cnblogs.com ...

  3. 获取Android系统默认给每个app分配的内存上限

    ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); int ...

  4. js右下角弹窗代码(实测好用)

    实测好用的js右下角弹窗代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt ...

  5. 社区管理有捷径!Wish3D Earth社区网格化管理案例重磅上线

    社区网格化是精细化.全覆盖.高效率的社区管理模式,便捷有效的社区网格化管理平台是社区网格化管理的关键. Wish3D Earth全新上线三维社区网格化管理平台,使用实景三维模型作为地图,地形地貌真实展 ...

  6. 微信小程序 - 单个题目

    后端传过来的数据,如果通过wx:for遍历出来那就是一个页面全部排下来.... 我的想法就是,页面初始化时设置一个默认值 1/50 就是 index+1 / 50(后端传过来的数组长度),通过控制in ...

  7. 2016年蓝桥杯C/C++B组

    第一次參加蓝桥杯.也是有非常多感触的,时间全然不够写最后一题... 最后一题没做...还有全排序非常重要... 1. 煤球数目 有一堆煤球,堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三 ...

  8. vue.js+koa2项目实战(一)创建项目和elementUI配置

    前端采用vuex+element-ui: 后端采用koa2+restfulAPI+sequlize: (一)项目介绍 宠物社区 1.社区 2.好友 3.说说 4.宠粮 5.健康 (二)项目框架 1.V ...

  9. MySQL之慢查询-删除慢查询日志

    一.环境 OS:CentOS release 5.8(64位) DB:MySQL5.5.17 二.操作         直接通过命令 rm -f  删除了慢查询日志 三.出现故障 慢查询日志没有自己主 ...

  10. Mybatis无法扫描到mapper.xml文件

    在Mybatis中默认扫描与mapper包同路径下的xml,resource文件的文件夹名称不能一次性创建,如com.baidu.mapper需要创建3次 这里如果是idea开发工具,一次创建与分开创 ...