关联组合操作
我将拥有多个子操作且其中一个子操作控制所有其他子操作的执行的所有操作称为关联组合操作。下列操作均属于这种类型: NESTED LOOPS、FILTER、UPDATE、CONNECT BY WITH FILTERING、UNION ALL (RECURSIVE WITH)以及BITMAP KEY ITERATION。 控制关联组合操作运行的规则除了之前10.3.1节中描述的规则之外,还包括以下规则。
Ø 拥有最小ID的子操作控制其他子操作的执行。
Ø 子操作从拥有最小ID的操作开始执行直到拥有最大ID的操作。但是,与无关联组合操作相反,它们不是顺序执行的,而是按某种交错的方式执行。
Ø 只有第一个子操作至多执行一次。其他所有子操作可能会执行多次或根本不执行。
即使这种类型的操作共享相同的特性,而它们当中的每一个,在某些方面,都有自己的行为。我们来看一下它们中各自的样例。注意接下来的部分提供的所有例子都是related-combine.sql脚本生成输出的摘录。
NESTED LOOPS操作
这个操作用于联接两组数据。因此,它总是有两个子操作,不能多也不能少。拥有最小ID的子操作被称为外循环或驱动行源。第二个操作被称为内循环。这个操作的特性是,外循环每返回一条数据,内循环都要执行一次。
下面的查询及其执行计划就是这样的例子(图10-5展示了它的父-子关系的图形表示):
select * FROM emp, dept
WHERE emp.deptno = dept.deptno
AND emp.comm IS NULL
AND dept.dname !='SALES';
在此执行计划中,NESTED
LOOPS操作的两个子操作都是独立操作。通过应用之前描述的规则,你会发现执行计划按以下顺序执行各个操作。
(1)操作0有一个子操作(1)。它不可能是第一个执行的操作。
(2)操作1有两个子操作(2)和(3),其中操作2是按升序排列的第一个。因此,操作2(外循环)是第一个被执行的操作。
(3)操作2扫描emp表,应用"EMP"."COMM"
IS NULL过滤谓词并将10行数据传递给它的父操作(1)。
(4)对于操作2返回的每一条数据,NESTED
LOOPS操作的第二个子操作,即内循环,都要执行一次。这是通过对比操作2的A-Rows列和操作3、操作4的Starts列确认的。
(5)内循环由两个独立的操作构成。根据应用于这种类型的操作的规则,操作4是在操作3之前被执行的。
(6)操作4通过应用"EMP"."DEPTNO"="DEPT"."DEPTNO"访问谓词来扫描dept_pk索引。这样做,它通过10次执行从索引上抽取10个rowid并传递给它的父操作(3)。
(7)操作3通过这10个从操作4返回的rowid访问dept表。对于每个rowid,都读取一行数据。接下来它应用"DEPT"."DNAME"'SALES'过滤谓词。这个过滤器导致两行数据被排除掉。它将剩余的8条数据传递给它的父操作(1)。
(8)操作1将这8条数据传递给它的父操作(0)。
(9)操作0将数据发送给调用者。