反连接

 反连接(Anti Join)是一种特殊的连接类型,与内连接和外连接不同,Oracle数据库里并没有相关的
关键字可以在SQL文本中专门表示反连接,所以这里把它单独拿出来说明。
为了方便说明反连接的含义,我们用“t1.x.anti=t2.y”来表示表T1和表T2做反连接,且T1是驱动表,T2
是被驱动表,反连接条件为t1.x=t2.y,这里“t1.x.anti=t2.y”的含义是只要表T2中有满足条件t1.x=t2.y
的记录存在,则表T1中满足条件t1.x=t2.y的记录就会被丢弃,最后返回的记录就是表T1中那些不满足
条件t1.x=t2.y的记录。
当做子查询展开时,Oracle经常会把那些外部where条件为NOT EXISTS,NOT IN或<>ALL的子查询转换成
对应的反连接。
我们来看如下的范例SQL1、2和3

SQL> select * from t1 where col2 not in (select col2 from t2);
SQL> select * from t1 where col2<>all (select col2 from t2);
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);

现在表T1和t2在各自的连接列COL2上均没有NULL值,在这种情况下范例SQL1、2、3实际上是等价的。


SQL> select * from t1 where col2 not in (select col2 from t2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------1  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed
SQL> select * from t1 where col2<>all (select col2 from t2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------1  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 2706079091---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="T1"."COL2")Statistics
----------------------------------------------------------1  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

上述3个范例SQL的执行结果是一样的,范例SQL1、2和范例SQL3的执行计划中,ID=1的执行步骤的列Operation的值分别为“HASH JOIN ANTI NA”和“HASH JOIN ANTI”,虽然不是完全一样,但它们都有关键字“ANTI”,这就说明Oracle在执行上述三个范例SQL时确实是在用反连接,即Oracle在执行时实际上是将他们转换成了如下的等价反连接形式:

select t1.* from t1,t2 where t1.col2 anti=t2.col2;

这里表T1、T2在各自的连接列COL2上没有NULL值,所以此时这三个范例SQL是等价的,但如果连接列COL2上有null值,则它们就不完全等价了。这种null值所带来的影响又细分为两种情况:
1、表T1的连接列COL2上出现了NULL值

SQL> insert into t1 values(4,null);1 row created.SQL> commit;Commit complete.

表T1中的记录如下:

SQL> select * from t1;COL1 C
---------- -1 A2 B3 C4

分别执行SQL1、2、3

SQL> select * from t1 where col2 not in (select col2 from t2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------1  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed
SQL> select * from t1 where col2 <>all (select col2 from t2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------1  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);COL1 C
---------- -43 CExecution Plan
----------------------------------------------------------
Plan hash value: 2706079091---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="T1"."COL2")Statistics
----------------------------------------------------------0  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size645  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)2  rows processed
SQL> delete from t1 where col1=4;1 row deleted.SQL> commit;Commit complete.

2、表T2的连接列COL2上出现了NULL值

SQL> insert into t2 values(null,'E2');1 row created.SQL> COMMIT;Commit complete. SQL> select * from t1;COL1 C
---------- -1 A2 B3 CSQL> select * from t2;C CO
- --
A A2
B B2
D D2E2    

再次执行上述三个SQL

SQL> select * from t1 where col2 not in (select col2 from t2);no rows selectedExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------0  recursive calls0  db block gets10  consistent gets0  physical reads0  redo size398  bytes sent via SQL*Net to client512  bytes received via SQL*Net from client1  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)0  rows processed
SQL> select * from t1 where col2 <>all (select col2 from t2);no rows selectedExecution Plan
----------------------------------------------------------
Plan hash value: 1275484728---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="COL2")Statistics
----------------------------------------------------------0  recursive calls0  db block gets10  consistent gets0  physical reads0  redo size398  bytes sent via SQL*Net to client512  bytes received via SQL*Net from client1  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)0  rows processed
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);COL1 C
---------- -3 CExecution Plan
----------------------------------------------------------
Plan hash value: 2706079091---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     7 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |      |     1 |     7 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     3 |    15 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     3 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - access("COL2"="T1"."COL2")Statistics
----------------------------------------------------------0  recursive calls0  db block gets12  consistent gets0  physical reads0  redo size590  bytes sent via SQL*Net to client523  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed
SQL> delete from t2 where col3='E2';1 row deleted.SQL> COMMIT;Commit complete.

从上述测试中我们可以得出以下结论:
1)表T1、T2在各自的连接列COL2上一但有了NULL值,则范例SQL1、2、3就不完全等价了。
2)NOT IN和<>ALL对NULL值敏感,这意味着NOT IN后面的子查询或者常量集合一旦有NULL值出现,则整个SQL的执行结果就会为NULL,即此时的执行结果将不包含任何记录。
3)NOT EXISTS对NULL值不敏感,这意味着NULL值对NOT EXISTS的执行结果不会有什么影响。正是因为NOT IN和<>ALL对NULL值敏感,所以一旦相关的连接列上出现NULL值,此时Oracle如果还按照通常的反连接的处理逻辑来处理,得到的结果就不对了。

为了解决NOT IN和<>ALL对NULL值敏感的问题,Oracle推出了改良的反连接,这种反连接能够处理NULL值,Oracle称其为Null-Aware Anti Join。上述范例SQL1、2的执行计划中,ID=1的执行步骤的列Operation的值为“HASH JOIN ANTI NA”,关键字NA就是Null-Aware的缩写。Oracle就是想告诉我们,这里采用的不是普通的哈希反连接,而是改良后的,能够处理NULL值的哈希反连接。

在Oracle 11g R2中,Oracle是否启用Null-Aware Anti Join受隐含参数_OPTIMIZER_NULL_AWARE_ANTIJOIN控制,其默认值为TRUE,表示启用Null-Aware Anti join。

如果我们把_OPTIMIZER_NULL_AWARE_ANTIJOIN的值修改为FALSE,则Oracle就不能再用Null-Aware Anti Join了,而又因为NOT IN对NULL值敏感,所以Oracle此时也不能用普通的反连接。

设置当前session中的_OPTIMIZER_NULL_AWARE_ANTIJOIN值为FALSE

alter session set "_OPTIMIZER_NULL_AWARE_ANTIJOIN"=false;

修改后执行范例SQL1:

#截图#
在这里插入图片描述
从上述显示内容可以看出,当我们把_OPTIMIZER_NULL_AWARE_ANTIJOIN的值修改为FALSE后,Oracle果然没有走反连接(当然也不能走)。
这里Oracle选择了走FILTER类型的执行计划,FILTER类型的执行计划实际上是一种改良的嵌套循环连接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916726.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916726.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916726.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

梳理一些 Docker 常用命令

以下是一些 Docker 常用命令&#xff0c;适用于日常开发、调试、部署等场景&#xff0c;分为几个常用类别&#xff1a;&#x1f4e6; 一、镜像&#xff08;Image&#xff09;相关命令命令说明docker images查看本地所有镜像docker pull <image>拉取镜像&#xff08;如 do…

C#_ArrayList动态数组

目录 ArrayList的特点 ArrayList 与普通数组的区别 使用示例&#xff1a; 普通数组 动态数组 主要方法和属性 属性&#xff1a; Count 获取动态数组的数据个数 读取某个位置的数据 // 索引 方法&#xff1a; Add 向集合末尾添加元素 Insert 在指定位置插入元…

Agent领域,近年来的前沿研究方向:多智能体协作、认知启发架构、伦理安全、边缘计算集成

Agent领域,近年来的前沿研究方向:多智能体协作、认知启发架构、伦理安全、边缘计算集成 在Agent领域,近年来的前沿研究方向主要集中在多智能体协作、认知启发架构、伦理安全、边缘计算集成以及生成式AI融合等方面。 一、多智能体协作与多模态任务 多智能体系统在复杂环境…

【安卓笔记】OOM与内存优化

0. 环境&#xff1a; 电脑&#xff1a;Windows10 Android Studio: 2024.3.2 编程语言: Java Gradle version&#xff1a;8.11.1 Compile Sdk Version&#xff1a;35 Java 版本&#xff1a;Java11 1.什么是OOM OOM即 OutOfMemoryError 内存溢出错误。常见于一些 资源型对…

持续集成CI与自动化测试

Python接口自动化测试零基础入门到精通&#xff08;2025最新版&#xff09;

Spring 策略模式实现

Spring 策略模式实现&#xff1a;工厂方法与自动注入详解 1. 背景介绍 在复杂的业务系统中,我们常常需要根据不同的场景选择不同的处理策略。本文将详细介绍在 Spring 框架中实现策略模式的两种主要方法。 2. 方案一: 手动注册工厂模式 2.1 定义工厂类 Component public class …

机器学习——线性回归(LinearRegression)

Python 线性回归详解&#xff1a;从原理到实战线性回归&#xff08;Linear Regression&#xff09;是机器学习中最基础也是最重要的算法之一&#xff0c;广泛应用于预测分析领域&#xff0c;例如房价预测、销售额预测等。本文将带你从理论出发&#xff0c;用 Python 手把手实现…

H.264视频的RTP有效载荷格式(翻译自:RFC6184 第5节 RTP有效载荷格式)

RTP协议格式 RFC地址&#xff1a;https://datatracker.ietf.org/doc/html/rfc6184 RTP报头的格式在RFC3550中指定 0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1------------------------…

秒级构建消息驱动架构:描述事件流程,生成 Spring Cloud Stream+RabbitMQ 代码

在消息驱动架构开发中&#xff0c;Spring Cloud Stream 与 RabbitMQ 的整合往往需要手动配置绑定器、定义消息通道、编写消费逻辑&#xff0c;流程繁琐且易出错。而飞算JavaAI 作为高效的 IDE 插件&#xff0c;能让开发者通过自然语言描述事件流程&#xff0c;自动生成可运行的…

从零搭建3D激光slam框架-基于mid360雷达节点实现

目录 MID360雷达介绍 雷达SDK编译与测试 雷达驱动的修改、编译与测试 去ros的编译方式 livox_ros_driver2的代码框架介绍 livox_ros_driver2编译 雷达IP配置文件介绍 常见问题介绍 优化改进 MID360雷达介绍 1 硬件介绍&#xff1a; livox-mid360是大疆的一款非重复扫描…

【Spring】日志级别的分类和使用

文章目录介绍日志级别的分类日志级别的顺序日志级别的使用介绍 日志级别代表着日志信息对应问题的严重性&#xff0c;为了更快的筛选符合目标的日志信息 试想一下这样的场景&#xff0c;假设你是一家 2 万人公司的老板&#xff0c;如果每个员工的日常工作和琐碎的信息都要反馈…

【C++】第十九节—一文万字详解 | AVL树实现

好久不见&#xff0c;我是云边有个稻草人&#xff0c;偶尔中二博主与你分享C领域专业知识^(*&#xffe3;(oo)&#xffe3;)^ 《C》—本篇文章所属专栏—持续更新中—欢迎订阅~喔 目录 一、AVL的概念 二、AVL树的实现 2.1 AVL树的结构 2.2 AVL树的插入 【AVL树插入⼀个值…

【Delphi】快速理解泛型(Generics)

Delphi的泛型&#xff08;generics&#xff09;是一项强大的特性&#xff0c;它使得代码更加灵活、类型安全&#xff0c;并且可以实现各种通用的数据结构和算法。下面我将为你详细介绍Delphi中的泛型&#xff0c;包括基本概念、语法、常用实例&#xff0c;以及使用建议。Delphi…

Java Stream流的使用

获取Stream流 单列集合直接使用stream()方法 List<String> list Arrays.asList("a", "b", "c"); Stream<String> stream list.stream(); // 获取顺序流数组使用静态方法Arrays.stream() String[] array {"a", "b&…

前端实现添加水印,两种方式

一、自定义指令的方式/*需求&#xff1a;给整个页面添加背景水印。思路&#xff1a;1、使用 canvas 特性生成 base64 格式的图片文件&#xff0c;设置其字体大小&#xff0c;颜色等。2、将其设置为背景图片&#xff0c;从而实现页面或组件水印效果使用&#xff1a;设置水印文案…

使用LangChain构建法庭预定智能体:结合vLLM部署的Qwen3-32B模型

文章目录 技术架构概述 核心实现步骤 1. 配置vLLM与Qwen3-32B模型 2. 定义工具(Tools) 3. 构建Agent系统 4. 运行与交互 关键技术亮点 1. 工具调用自动化 2. Hermes解析器优势 3. 对话记忆管理 实际运行效果 性能优化建议 扩展应用场景 总结 在人工智能应用开发中,如何让大语…

vscode开发微信小程序

下载插件 插件下载位置 1.微信小程序开发工具 2.vscode weapp api 3.vscode wxml 4.vscode-wechat 创建项目 终端运行命令 cd 到要创建项目的目录执行命令&#xff1a;vue create -p dcloudio/uni-preset-vue test test就是项目名称 选择默认模板&#xff0c;回车 出现下图这…

板凳-------Mysql cookbook学习 (十二--------3_3)

https://cloud.tencent.com/developer/article/1454690 侯哥的Python分享 # 创建节点 class Node(object):def __init__(self,item):self.element itemself.next None# 创建单链表类 class SingleLinkList(object):def __init__(self):self.header Noneself.length 0# 1、判…

Flutter开发实战之CI/CD与发布流程

第12章:CI/CD与发布流程 在前面的章节中,我们学习了Flutter应用开发的各个方面,从基础UI构建到复杂的状态管理,从网络请求到本地存储。现在,我们将探讨一个同样重要但常被忽视的话题:如何将我们精心开发的应用高效、可靠地发布到各大应用商店。 想象一下,你花费了数月…

ElasticSearch 的3种数据迁移方案

在实际工作中&#xff0c;我们经常会遇到需要将自建的 Elasticsearch 迁移上云&#xff0c;或者迁移到其他 ES 集群的情况。这时&#xff0c;选择合适的数据迁移方案就显得尤为重要啦。今天就来给大家介绍三种常用的迁移方案&#xff0c;分别是 COS 快照、logstash 和 elastics…