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

在Oracle中,什么是反连接(Anti Join)?

DB宝 2019-07-08
4328


题目部分

在Oracle中,什么是反连接(Anti Join)?


     

答案部分


反连接(Anti Join)也是一种特殊的连接类型,通常用于从一个表中返回不在另一个数据源中的数据行。当做子查询展开时,Oracle经常会把那些外部WHERE条件为NOT EXISTSNOT IN<> ALL的子查询转换成对应的反连接。反连接分为嵌套循环反连接(NESTED LOOPS ANTIHint为:NL_AJ)、排序合并反连接(MERGE JOIN ANTIHint为:MERGE_AJ)和哈希反连接(HASH JOIN ANTIHint为:HASH_AJ)。示例如下所示:

 1CREATE TABLE EMP AS SELECT * FROM SCOTT.EMP;
2CREATE TABLE DEPT AS SELECT * FROM SCOTT.DEPT;
3SELECT * FROM EMP A WHERE NOT EXISTS(SELECT 1 FROM DEPT WHERE DEPTNO=A.DEPTNO);
4---------------------------------------------------------------------------
5| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
6---------------------------------------------------------------------------
7|   0 | SELECT STATEMENT   |      |     2 |    84 |     5  (20)| 00:00:01 |
8|*  1 |  HASH JOIN ANTI    |      |     2 |    84 |     5  (20)| 00:00:01 |
9|   2 |   TABLE ACCESS FULL| EMP  |    12 |   468 |     2   (0)| 00:00:01 |
10|   3 |   TABLE ACCESS FULL| DEPT |     4 |    12 |     2   (0)| 00:00:01 |
11---------------------------------------------------------------------------
12SELECT * FROM EMP A WHERE NOT EXISTS(SELECT /*+NL_AJ*/ 1 FROM DEPT WHERE DEPTNO=A.DEPTNO);
13---------------------------------------------------------------------------
14| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
15---------------------------------------------------------------------------
16|   0 | SELECT STATEMENT   |      |     2 |    84 |     7   (0)| 00:00:01 |
17|   1 |  NESTED LOOPS ANTI |      |     2 |    84 |     7   (0)| 00:00:01 |
18|   2 |   TABLE ACCESS FULL| EMP  |    12 |   468 |     2   (0)| 00:00:01 |
19|*  3 |   TABLE ACCESS FULL| DEPT |     4 |    12 |     0   (0)| 00:00:01 |
20---------------------------------------------------------------------------
21SELECT * FROM EMP A WHERE NOT EXISTS(SELECT /*+MERGE_AJ*/ 1 FROM DEPT WHERE DEPTNO=A.DEPTNO);
22----------------------------------------------------------------------------
23| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
24----------------------------------------------------------------------------
25|   0 | SELECT STATEMENT    |      |     2 |    84 |     6  (34)| 00:00:01 |
26|   1 |  MERGE JOIN ANTI    |      |     2 |    84 |     6  (34)| 00:00:01 |
27|   2 |   SORT JOIN         |      |    12 |   468 |     3  (34)| 00:00:01 |
28|   3 |    TABLE ACCESS FULL| EMP  |    12 |   468 |     2   (0)| 00:00:01 |
29|*  4 |   SORT UNIQUE       |      |     4 |    12 |     3  (34)| 00:00:01 |
30|   5 |    TABLE ACCESS FULL| DEPT |     4 |    12 |     2   (0)| 00:00:01 |
31----------------------------------------------------------------------------

需要注意的是,NOT IN<> ALLNULL值敏感,这意味着NOT IN后面的子查询或者常量集合一旦有NULL值出现,则整个SQL的执行结果就会为NULL,即此时的执行结果将不包含任何记录。但是,NOT EXISTSNULL值不敏感,这意味着NULL值对NOT EXISTS的执行结果不会有什么影响。正是因为NOT IN<> ALLNULL值敏感,所以一旦相关的连接列上出现了NULL值,此时Oracle如果还按照通常的反连接的处理逻辑来处理,得到的结果就不对了。为了解决NOT IN<> ALLNULL值敏感的问题,Oracle推出了改良的反连接,这种反连接能够处理NULL值,Oracle称其为Null-Aware Anti Join,如下例:

1SELECT * FROM DEPT A WHERE DEPTNO NOT IN (SELECT DEPTNO FROM EMP);
2---------------------------------------------------------------------------
3| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
4---------------------------------------------------------------------------
5|   0 | SELECT STATEMENT   |      |     1 |    23 |     5  (20)| 00:00:01 |
6|*  1 |  HASH JOIN ANTI NA |      |     1 |    23 |     5  (20)| 00:00:01 |
7|   2 |   TABLE ACCESS FULL| DEPT |     4 |    80 |     2   (0)| 00:00:01 |
8|   3 |   TABLE ACCESS FULL| EMP  |    12 |    36 |     2   (0)| 00:00:01 |
9---------------------------------------------------------------------------

执行步骤的列Operation的值为“HASH JOIN ANTI NA”,关键字“NA”就是Null-Aware的缩写,表示这里采用的不是普通的哈希反连接,而是改良后的、能够处理NULL值的哈希反连接。

Oracle 11gR2中,Oracle是否启用Null-Aware Anti Join受隐含参数“_OPTIMIZER_NULL_AWARE_ANTIJOIN”控制,其默认值为TRUE,表示启用Null-Aware Anti Join。如果把该参数的值修改为FALSE,那么表示Oracle就不能再用Null-Aware Anti Join了,而又因为NOT INNULL值敏感,所以Oracle此时也不能用普通的反连接。关于该隐含参数的查询如下所示:

 1SYS@orclasm > set pagesize 9999
2SYS@orclasm > set line 9999
3SYS@orclasm > col NAME format a40
4SYS@orclasm > col KSPPDESC format a50
5SYS@orclasm > col KSPPSTVL format a20
6SYS@orclasm > SELECT a.INDX,
7  2         a.KSPPINM NAME,
8  3         a.KSPPDESC,
9  4         b.KSPPSTVL 
10  5  FROM   x$ksppi  a,
11  6         x$ksppcv b
12  7  WHERE  a.INDX = b.INDX
13  8  and lower(a.KSPPINM) like  lower('%&parameter%');
14Enter value for parameter: _OPTIMIZER_NULL_AWARE_ANTIJOIN
15old   8: and lower(a.KSPPINM) like  lower('%&parameter%')
16new   8: and lower(a.KSPPINM) like  lower('%_OPTIMIZER_NULL_AWARE_ANTIJOIN%')
17
18      INDX NAME                                     KSPPDESC                                           KSPPSTVL
19---------- ---------------------------------------- -------------------------------------------------- --------------------
20      1907 _optimizer_null_aware_antijoin           null-aware antijoin parameter                      TRUE




本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。



---------------优质麦课------------

 详细内容可以添加麦老师微信或QQ私聊。



About Me:小麦苗

 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用

● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/

 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

 版权所有,欢迎分享本文,转载请保留出处

 QQ:646634621  QQ群:618766405

 提供OCP、OCM和高可用部分最实用的技能培训

● 题目解答若有不当之处,还望各位朋友批评指正,共同进步

DBA宝典

长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。

喜欢就点击“好看”吧



最后修改时间:2020-01-10 19:48:25
文章转载自DB宝,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论