Oracle優化學習十六

反連接

?反連接(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…