暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

关于表连接方法的学习-嵌套循环

原创 张伟垚 2020-05-28
1252

在oracle数据库中,表的连接方法有排序合并连接、嵌套循环连接、哈希连接以及笛卡尔连接,针对自我学习和理解,在这里进行梳理:

嵌套循环连接

FOR erow IN (select * from employees where X=Y) LOOP
FOR drow IN (select * from departments where erow is matched) LOOP
output values from erow and drow
END LOOP
END LOOP

首先看看oracle官方文档copy过来的嵌套循环伪代码,两个表对应两个for循环,第一个for循环遍历筛选出第一个表中符合条件的数据,然后用第一个循环获得的结果集去遍历第二个表中符合条件的数据进行匹配,边匹配边输出符合匹配条件的数据。其中具有驱动表和被驱动表的概念,第一层循环的表作为驱动表,而第二层循环的表作为被驱动表。

下面进行实验测试一下:

如果是两个表都没有索引的情况下会是怎么循环呢?

image.png

1、通过过滤条件ename like ‘A*’ 对emp_temp表进行全表扫描,这一步得到的结果集作为nested loop的外循环表,也就是驱动结果集(emp.* where ename like ‘A*’ )。
image.png

2、通过第1步的驱动结果集(emp.* where ename like ‘A*’)中的dept直接去循环匹配dept_temp的deptno,由于这里的驱动结果集是2条记录,所以dept_temp也被访问2次,得到的结果(ename,dname)进行合并返回请求行。

如果是有索引的情况下呢?

image.png
首先查看需要关联查询的两个测试表的数据。

emp和dept的关联在于dept字段,查询emp表中,ename为A开头以及它的dept_name。

image.png
可以看到这里有两个nested loop,执行步骤为4-3-5-2-6-1

具体的步骤如下:

1、在emp表中,通过ename like 'A%'条件过滤需要的数据,这一步通过ename列的索引ind_emp_name进行索引范围扫描,得到的结果集是(empno,rowid)。(对应id=4)

2、通过第1步索引范围扫描的rowid返回表查询相应的表数据。(对应id=3)并且这里的结果集作为第一个nested loop的外部表循环,也就是驱动结果集。这里实际上emp也只访问了一次,这里start=1可以证明,这是因为通过rowid回表查询表数据得到所需要的deptno(ename,deptno,rowid)。
image.png
所以以上两步所做的事情如上图所示,得到一个这样的结果集(结果集记录数为2)。

3、在dept表中,通过d.deptno进行索引唯一扫描,因为deptno在dept表中是主键(对应id=5),这里的结果集是dept的通过索引唯一扫描出来的rowid和deptno,作为第一个nested loop的内部表,也就是被驱动结果集。

image.png
第三步的结果集是(deptno,rowid),结果集记录数为4。

4、第2步的结果集(ename,deptno,rowid)和第3步的结果集(deptno,rowid)通过e.deptno=d.deptno进行遍历匹配,这是第一个nested loop循环。(对应id=2)
image.png
第一个nesed loop遍历之后的结果集如上图所示。

5、由于第四步的结果集产生了两条记录数也就是第二nested loop的驱动表,这里的循环将上一步获得的结果集对dept表进行遍历,也是通过b.rowid进行循环遍历dept获取需要的列dname,然后将结果(ename,dname)合并返回请求行。

以上就是两个nested loop的过程。

小结

可以看出,如果驱动表过滤后的驱动结果集很少,被驱动表的连接列存在唯一索引,或者选择性很高的非唯一索引,但前提是被驱动结果集的数量也不是很大,这样的嵌套循环效率是很高的,所以大表不一定不适合做驱动表,关键在于过滤条件能否将驱动结果集的数量降下来。
另外,嵌套循环可以实现快速响应,也就是第一时间返回已经连接过并且满足连接条件的记录(我理解为边遍历边返回请求行),而排序合并需要排序完后,开始合并操作时才能返回,哈希连接需要驱动结果集对应的HASH TABLE全部建立完后才开始返回数据。

PS:以上均为个人学习之后的理解,如有错误,恳请指正。
学习资料:《oracle官方文档》、《基于oracle的sql优化》

最后修改时间:2020-05-28 23:05:23
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论