关联组合操作 FILTER 操作 UPDATE 操作

2023年 11月 16日 98.5k 0

  FILTER 操作

这个操作的特性是支持不同数量的子操作。如果它拥有一个单独的子操作,就可以将它视为一个独立操作。如果它拥有两个或更多的子操作,则其功能与NESTEDLOOPS操作类似。第一个子操作驱动其他子操作的执行。

 

为了说明这一点,我们来看下面的查询及其执行计划(图10-6展示了其父-子关系的图形表示):

select * FROM emp

WHERE NOT EXISTS(select 0 from dept WHERE
dept.dname ='SALES' AND dept.deptno = emp.deptno)

AND NOT EXISTS(select 0 FROM bonus WHERE
bonus.ename = emp.ename);

 

 

警告 dbms_xplan包中的display_cursor函数有时候会显示错误的谓词。然而,问题并不在于程序包。实际上是由显示错误信息的v$sql_plan和v$sql_plan_statistics_all视图引起的。在这种情况下,EXPLAIN PLAN为上面显示的计划显示正确的谓词,但是视图为操作1显示了一个错误的谓词:

1 - filter((IS NULL AND IS NULL))

 

注意,根据Oracle的说法,这不是一个bug,只是当前实现的一个限制。

 

在这个执行计划中,FILTER操作的三个子操作为独立操作。应用之前描述的规则,你可以发现执行计划按以方式执行各个操作。

(1)操作0有一个子操作(1)。它不可能是第一个被执行的操作。

(2)操作1有三个子操作(2、3和5),操作2是它们当中按升序排列的第一个。因此,执行从操作2开始。

(3)操作2扫描emp表并将14条数据返回给它的父操作(1)。

(4)对于操作2返回的每条数据,FILTER操作的第二个和第三个子操作都应该执行一次。而实际上,某种缓存被实现以将执行减至最少。这是通过将操作2的A-Rows列与操作3、5的Starts列相对比得知的。操作3被执行了三次,为emp表的deptno列的每个不重复值执行了一次。操作5执行了八次,为emp表在应用完由操作3施加的过滤器之后的ename列的每个不重复值执行了一次。下面的查询表明starts列的数值和不重复值的数量相匹配:

select deptno, dname,count(*)

FROM emp NATURAL JOIN dept

GROUP BY deptno, dname;

(5)根据独立操作的规则,操作4是在操作3之前执行的,通过应用"DEPT"."DEPTNO"=:B1访问谓词来扫描dept_pk索引。绑定变量(B1)用来传递通过子查询检查的值。通过在三次执行中都这样做,操作从索引中提取三个rowid并将它们传递给它的父操作(3)。

(6)操作3通过从它的子操作(4)传递过来的rowid访问dept表并应用"DEPT"."DNAME"='SALES'过滤谓词。因为这个操作只是用来应用一个限制条件,它不向父操作(1)返回任何数据。它仅通知父操作条件是否满足。无论如何,应该注意到只找到一行满足过滤谓词的数据。因为使用了NOT EXISTS,这个匹配的行被丢弃掉了。

(7)操作5扫描bonus表并应用"BONUS"."ENAME"=:B1过滤谓词。绑定变量(B1)用来传递通过子查询检查的值。因为这个操作只用于应用一个限制条件,它不向其父操作(1)返回任何数据。但是要注意没有找到满足过滤谓词的数据。因为使用了NOT EXISTS,没有数据被丢弃掉。

(8)在应用完由操作3和操作5实现的过滤谓词后,操作1将结果数据返回给它的父操作(0)。

(9)操作0将数据发送给调用者。

  UPDATE 操作

这个操作是执行某个UPDATE语句时使用的。它的特性是支持不同数量的子操作。大多数时候,它拥有一个单独的子操作而且因此被认为是独立操作。只有在SET子句中使用子查询时,才会有两个或更多的子操作可用。如果它拥有不止一个子操作,那么第一个子操作驱动其他子操作的执行。

 

下面是一个样例SQL语句及其执行计划(图10-7展现了它的父-子关系的图形表示):

UPDATE emp e1

SET sal=(select avg(sal) FROM emp e2 WHERE
e2.deptno = e1.deptno),

   
comm=(select avg(comm) FROM emp e3);

 

4 -
filter("E2"."DEPTNO"=:B1)

 

在这个执行计划中,UPDATE关联组合操作的全部三个子操作都是独立操作。之前描述的规则表明执行计划按以下方式执行各个操作。

(1)操作0有一个子操作(1)。它不可能是第一个被执行的操作。

(2)操作1有三个子操作(2、3和5),且操作2是这三个中按升序排列的第一个。因此,执行从操作2开始。

(3)操作2扫描emp表并向它的父操作(1)返回14行数据。

(4)第二个和第三个子操作(3和5)可能会被执行多次(最多会与操作2返回的行数相等)。因为这些操作都是独立的,且每个操作都有一个子操作,它们的执行从子操作(4和6)开始。

(5)对于由操作2返回的deptno列中的每个不重复值,操作4扫描emp表并应用"E2"."DEPTNO"=:B1过滤谓词。通过在三次执行中这么做,操作提取出14行数据并将它们传递给它的父操作(3)。

(6)操作3计算从操作4传递给它的数据的平均工资,并将结果返回给它的父操作(1)。

(7)操作6扫描emp表,提取14行数据,并将它们传递给它的父操作(5)。注意这个子查询只执行了一次,因为它并不与主查询相互关联。

(8)操作5计算从操作6传递给它的数据的平均佣金,并将结果返回给它的父操作(1)。

(9)操作1使用它的子操作(3和5)返回的值来更新由操作2传递过来的每一行数据,并向它的父操作(0)传递更新的行数。注意,即使UPDATE语句修改了这14行数据,这个操作的A-Rows列仍显示为0。

(10)操作0向调用者发送被修改的行数。

 

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论