一、基本概念
嵌套循环连接(Nested Loops Join)是一种两个表在做表连接时依靠两层嵌套循环(分别为外层循环和内层循环)来得到连接结果集的表连接方法。
如果两个表(这里将它们分别命名为表T1和表T2)在做表连接时使用的是嵌套循环连接,则Oracle会依次顺序执行如下步骤。
(1)首先,优化器会按照一定的规则来决定表T1和T2中谁是驱动表、谁是被驱动表。驱动表用于外层循环,被驱动表用于内层循环。这里假设驱动
表是T1,被驱动表是T2。
(2)接着以目标SQL中指定的谓词条件(如果有的话)去访问驱动表T1,访问驱动表T1后得到的结果集我们记为驱动结果集1。
(3)然后遍历驱动结果集1并同时遍历被驱动表T2,即先取出驱动结果集1中的第1条记录,接着遍历被驱动表T2并按照连接条件去判断T2中是否存
在匹配的记录,然后再取出驱动结果集1中的第2条记录,按照同样的连接条件再去遍历被驱动表T2并判断T2中是否还存在匹配的记录,直到遍
历完驱动结果集1中所有的记录为止。这里的外层循环是指遍历驱动结果集1所对应的循环,内层循环是指遍历被驱动表T2所对应的循环。显然,
外层循环所对应的驱动结果集1有多少条记录,遍历被驱动表T2的内层循环就要做多少次,这就是所谓的“嵌套循环”的含义。
二、俗话说嵌套循环连接的执行过程
嵌套循环连接被称为是程序员的思维,其执行过程就是取出驱动表的结果集的值,每个值对被驱动表的结果集进行遍历,继续下一个驱动表的结果
集的值,直到完成所有驱动表的值对被驱动表的遍历。
示例:
select * from dw0810 a , dw0810a b where a.object_id=b.object_id;
该sql的执行过程:假设a表是驱动表,b表是被驱动表,
for id in (select object_id from dw0810 a)
do selct * from dw0810a b where b.object_id =:id ---a表有多少行,对b表就遍历多少次
done
三、查看数据库中的执行计划
select /*+ use_nl(a,b) */ * from dw0810 a , dw0810a b where a.object_id=b.object_id and a.object_id=20
Plan Hash Value : 3096268616
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 196 | 4 | 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 196 | 4 | 00:00:01 |
| 2 | NESTED LOOPS | | 1 | 196 | 4 | 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID | DW0810A | 1 | 98 | 2 | 00:00:01 |
| * 4 | INDEX RANGE SCAN | IDX_DW0810A | 1 | | 1 | 00:00:01 |
| * 5 | INDEX RANGE SCAN | IDX_DW0810 | 1 | | 1 | 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID | DW0810 | 1 | 98 | 2 | 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 4 - access("B"."OBJECT_ID"=20)
* 5 - access("A"."OBJECT_ID"=20)
如果a表及b表有过滤条件,先对其进行过滤,示例过滤条件有索引,可以高效过滤数据
四、注意事项:
1、如果驱动表所对应的驱动结果集的记录数较少,同时在被驱动表的连接列上又存在唯一性索引(或者在被驱动表的连接列上存在选择性很好的非
唯一性索引),那么此时使用嵌套循环连接的执行效率就会非常高
2、如果驱动表所对应的驱动结果集的记录数很多,即便在被驱动表的连接列上存在索引,此时使用嵌套循环连接的执行效率也不会高
3、大表也可以作为嵌套循环连接的驱动表,关键看目标SQL中指定的谓词条件(如果有的话)能否将驱动结果集的数据量降下来
4、嵌套循环连接有其他连接方法所没有的一个优点:嵌套循环连接可以实现快速响应,即它可以第一时间先返回已经连接过且满足连接条件的记录,
而不必等待所有的连接操作全部做完后才返回连接结果。虽然排序合并连接和哈希连接也可以先返回已经连接过且满足连接条件的记录,而不必等待
所有的连接操作都做完,但是它们并不是第一时间返回,因为排序合并连接要等到排完序后做合并操作时才能开始返回数据,而哈希连接则要等到驱
动结果集所对应的Hash Table全部建完后才能开始返回数据
5、如果统计信息不准或者对谓词条件预估驱动表结果集时,如果预估的比较小,如驱动表结果集为1,让执行计划走上嵌套循环连接时,就非常容易
产生性能问题,所以在nl连接时,分析此处的预估值是否正确,并可以测试使用hash连接是否更高效。




