MySQL中IN關鍵字與EXIST關鍵字的比較

文章目錄

      • **功能等價性分析**
        • **執行計劃分析**:
      • **1. `EXISTS` 的工作原理**
        • **步驟拆解**:
      • **2. 為什么需要“利用索引快速定位”?**
        • **索引作用示例**:
      • **3. 與 `IN` 子查詢的對比**
        • **`IN` 的工作方式**:
        • **關鍵差異**:
      • **4. 性能優化核心**
      • **5. 實際案例驗證**
        • **場景**:
        • **執行計劃分析**:
        • **結果**:
      • **6. 總結**
        • **效率總結**:
      • **5. 最終建議**

問題:
首先說明下面兩句MYSQL語句實現的功能是否一樣,接著比較它們的執行效率:

SELECT * from tableA where tableA.id in (select id from tableB)
SELECT * FROM tableA 
WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.id = tableB.id);

答:當 id 無 NULL 值且唯一時,兩者功能一致。另外,第二句中的子查詢使用 SELECT 1(最佳實踐,無需實際列值)。通常情況下(id是主鍵,tableA 和 tableB 數據量較大,id 字段有索引。),第二句效率更高。


功能等價性分析

場景IN 的行為EXISTS 的行為
子查詢無 NULL等價等價
子查詢含 NULLtableA.id IN (1, NULL) 等價于 tableA.id=1 OR tableA.id=NULL,最終只有 id=1 的行匹配EXISTS 只要子查詢有匹配(即使含 NULL)就會返回 TRUE

結論

  • tableB.id NULL 值且唯一時,兩者功能一致。
  • tableB.idNULL 或重復值時,結果可能不同。

執行計劃分析
方法優化策略適用場景
IN 子查詢MySQL 可能將子查詢物化為臨時表,再通過 JOIN 或半連接優化。子查詢結果集較小時效率高。
EXISTStableA 的每一行觸發一次關聯子查詢,利用索引快速定位。tableA 較小且 tableB.id 有索引時效率高。

1. EXISTS 的工作原理

EXISTS 是一種 關聯子查詢(Correlated Subquery),其核心邏輯是:
對于外層查詢(tableA)的每一行,觸發一次內層子查詢(tableB)的檢查
具體流程如下:

步驟拆解
  1. 遍歷外層表(tableA
    逐行讀取 tableA 的數據,取當前行的 id 值(例如 id=100)。

  2. 執行子查詢(tableB
    將外層 tableA.id=100 傳入子查詢,檢查 tableB 中是否存在匹配的 id

    SELECT 1 FROM tableB WHERE id = 100;  -- 當前外層行的 id 值
    
  3. 判斷結果

    • 若子查詢返回至少一行結果 → EXISTSTRUE → 保留當前外層行。
    • 若子查詢無結果 → EXISTSFALSE → 丟棄當前外層行。
  4. 循環處理
    重復上述過程,直到 tableA 所有行處理完畢。


2. 為什么需要“利用索引快速定位”?

在上述流程中,子查詢 SELECT 1 FROM tableB WHERE id=100 需要快速判斷 id=100 是否存在。
tableB.id 沒有索引

  • 數據庫需對 tableB 進行全表掃描 → 時間復雜度為 O(N),性能極差(尤其當 tableB 數據量大時)。

tableB.id 有索引(如主鍵索引或普通索引):

  • 數據庫通過索引(如 B+Tree)直接定位到 id=100 → 時間復雜度為 O(logN),效率極高。
索引作用示例
  • 假設 tableB 有 100 萬行數據:
    • 無索引:每次子查詢需掃描 100 萬行 → 總成本:1,000,000(外層行數) × 1,000,000(內層掃描) → 不可接受。
    • 有索引:每次子查詢僅需 3~4 次磁盤 I/O(B+Tree 高度) → 總成本:1,000,000(外層行數) × 4(索引查詢) → 高效。

3. 與 IN 子查詢的對比

IN 的工作方式
SELECT * FROM tableA WHERE id IN (SELECT id FROM tableB);
  1. 執行子查詢
    先執行 SELECT id FROM tableB,生成一個臨時結果集(如 [1, 2, 3])。

  2. 遍歷外層表(tableA
    逐行檢查 tableA.id 是否在臨時結果集中。

關鍵差異
特性EXISTSIN
子查詢執行次數外層表行數(N次)1次
臨時表物化無需物化需要物化子查詢結果到臨時表
索引依賴依賴內層表(tableB)的索引依賴外層表(tableA)的索引
NULL 值處理不受子查詢中 NULL 影響IN 遇到 NULL 可能導致結果異常

4. 性能優化核心

  • EXISTS 高效的核心條件

    • 內層表(tableB)的關聯字段(id)必須有索引。
    • 外層表(tableA)的數據量不宜過大(否則逐行觸發子查詢的總成本仍可能較高)。
  • IN 高效的核心條件

    • 子查詢結果集較小,且外層表(tableA)的 id 字段有索引。

5. 實際案例驗證

場景
  • tableA:10,000 行,id 無索引
  • tableB:1,000,000 行,id 有唯一索引
執行計劃分析
  1. EXISTS 查詢

    • tableA 的 10,000 行逐行觸發子查詢。
    • 每次子查詢通過索引在 tableB 中快速定位 → 總成本 ≈ 10,000 × 4 I/O = 40,000 I/O。
  2. IN 查詢

    • 先執行 SELECT id FROM tableB,生成 1,000,000 行的臨時表。
    • tableA 的 10,000 行逐行在臨時表中搜索 → 總成本 ≈ 1,000,000(物化) + 10,000 × 1,000,000(全掃描) → 性能災難。
結果
  • EXISTS 明顯優于 IN,尤其在子查詢結果集大且內層表有索引時。

6. 總結

  • EXISTS 的本質:通過外層表驅動循環 + 內層索引快速定位,避免全表掃描。
  • 何時選擇 EXISTS
    • 內層表(子查詢表)的關聯字段有索引。
    • 外層表數據量適中,或內層表數據量遠大于外層表。
  • 驗證方法
    EXPLAIN SELECT * FROM tableA 
    WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.id = tableB.id);
    
    檢查執行計劃中是否出現 Using index(表示索引生效)。
效率總結
  1. EXISTS 通常更高效
    • 避免物化臨時表。
    • 通過索引快速判斷是否存在匹配。
  2. IN 可能更高效的情況
    • 子查詢結果集非常小且無索引。
    • 優化器將 IN 轉換為 JOIN 并應用哈希/排序優化。

5. 最終建議

  • 優先使用 EXISTS:語義更清晰,且通常性能更優。
  • 強制功能一致性:若需嚴格匹配 IN 的行為(處理 NULL),可添加過濾條件:
    SELECT * FROM tableA 
    WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.id = tableB.id AND tableB.id IS NOT NULL  -- 顯式排除 NULL 值
    );
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897685.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897685.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897685.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

## DeepSeek寫水果記憶配對手機小游戲

DeepSeek寫水果記憶配對手機小游戲 提問 根據提的要求,讓DeepSeek整理的需求,進行提問,內容如下: 請生成一個包含以下功能的可運行移動端水果記憶配對小游戲H5文件: 要求 可以重新開始游戲 可以暫停游戲 卡片里的水果…

【含文檔+PPT+源碼】基于Django框架的鄉村綠色農產品交易平臺的設計與實現

項目介紹 本課程演示的是一款基于Django框架的鄉村綠色農產品交易平臺的設計與實現,主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Python學習者。 1.包含:項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運…

idea超級AI插件,讓 AI 為 Java 工程師

引言? 用戶可在界面中直接通過輸入自然語言的形式描述接口的需求,系統通過輸入的需求自動分析關鍵的功能點有哪些,并對不確定方案的需求提供多種選擇,以及對需求上下文進行補充,用戶修改確定需求后,系統會根據需求設…

@RestControllerAdvice注解

RestControllerAdvice RestControllerAdvice 是 Spring Framework(3.2)和 Spring Boot 中用于全局處理控制器層異常和統一響應格式的注解。它結合了 ControllerAdvice 和 ResponseBody 的功能,能夠攔截控制器方法拋出的異常,并以 …

ActiveMQ監聽器在MQ重啟后不再監聽問題

應用的監聽器注解 JmsListener(destination "TopicName",containerFactory "FactoryName")工廠代碼 BeanJmsListenerContainerFactory<?> FactoryName(ConnectionFactory connectionFactory){SimpleJmsListenerContainerFactory factory new S…

大白話 Vue 中的keep - alive組件,它的作用是什么?在什么場景下使用?

大白話 Vue 中的keep - alive組件&#xff0c;它的作用是什么&#xff1f;在什么場景下使用&#xff1f; 什么是 keep-alive 組件 在 Vue 里&#xff0c;keep-alive 是一個內置組件&#xff0c;它就像是一個“保存盒”&#xff0c;能把組件實例保存起來&#xff0c;而不是每次…

考研復試c語言常見問答題匯總2

11. 關鍵字和一般標識符有什么不同&#xff1f; C語言中關鍵字與一般標識符區別&#xff1a; 定義&#xff1a;關鍵字是C語言預定義的特殊單詞&#xff08;如int、for&#xff09;&#xff0c;有固定含義&#xff1b;標識符是自定義的名稱&#xff08;如變量名、函數名&#xf…

Scala編程_實現Rational的基本操作

在Scala中實現一個簡單的有理數&#xff08;Rational&#xff09;類&#xff0c;并對其進行加法、比較等基本操作. 有理數的定義 有理數是可以表示為兩個整數的比值的數&#xff0c;通常形式為 n / d&#xff0c;其中 n 是分子&#xff0c;d 是分母。為了確保我們的有理數始終…

若依框架-給sys_user表添加新字段并獲取當前登錄用戶的該字段值

目錄 添加字段 修改SysUser類 修改SysUserMapper.xml 修改user.js 前端獲取字段值 添加字段 若依框架的sys_user表是沒有age字段的&#xff0c;但由于業務需求&#xff0c;我需要新添加一個age字段&#xff1a; 修改SysUser類 添加age字段后&#xff0c;要在SysUser類 …

霍夫變換法是基于傳統視覺特征的道路車道線檢測算法中的一種經典方法

霍夫變換法是基于傳統視覺特征的道路車道線檢測算法中的一種經典方法&#xff0c;以下是對它的詳細介紹&#xff1a; 基本原理 霍夫變換的基本思想是將圖像空間中的點映射到參數空間中&#xff0c;通過在參數空間中尋找峰值來確定圖像中特定形狀的參數。在車道線檢測中&#…

【論文筆記】Best Practices and Lessons Learned on Synthetic Data for Language Models

論文信息 論文標題&#xff1a;Best Practices and Lessons Learned on Synthetic Data for Language Models 作者信息&#xff1a; Ruibo Liu, Jerry Wei, Fangyu Liu, Chenglei Si, Yanzhe Zhang, Jinmeng Rao, Steven Zheng, Daiyi Peng, Diyi Yang, Denny Zhou1 and Andre…

Android調試工具之ADB

Android Debug Bridge ADB介紹**一、ADB下載****二、ADB安裝****三、ADB基礎使用命令** ADB介紹 ADB&#xff08;Android Debug Bridge&#xff09;是Android開發與調試的必備工具&#xff0c;掌握它能極大提升開發效率。 一、ADB下載 Windows版本&#xff1a;https://dl.goo…

第三篇《RMAN 備份與恢復指南:保障數據庫安全》(RMAN)

《Oracle 數據遷移與備份系列》 第三篇&#xff1a;《RMAN 備份與恢復指南&#xff1a;保障數據庫安全》&#xff08;RMAN&#xff09; 1.概述 RMAN&#xff08;Recovery Manager&#xff09; 是 Oracle 數據庫內置的專用備份與恢復工具&#xff0c;提供高效、安全的物理級數…

【測試框架篇】單元測試框架pytest(4):assert斷言詳解

一、前言 用例三要素之一就是對預期結果的斷言。 何為斷言&#xff1f;簡單來說就是實際結果和期望結果去對比&#xff0c;符合預期就測試pass&#xff0c;不符合預期那就測試 failed。斷言內容就是你要的預期結果。斷言包含對接口響應內容做斷言、也包含對落DB的數據做斷言。…

什么是大模型微調?

在大模型&#xff08;如GPT、BERT、LLaMA等&#xff09;廣泛應用的今天&#xff0c;“微調”&#xff08;Fine-Tuning&#xff09;已成為釋放模型潛力的關鍵技術。它通過針對特定任務調整預訓練模型&#xff0c;使其從“通才”變為“專才”。本文將從概念、原理到實踐&#xff…

C# Channel

核心概念創建Channel無界通道有界通道FullMode選項 生產者-消費者模式生產者寫入數據消費者讀取數據 完整示例高級配置優化選項&#xff1a;取消操作&#xff1a;通過 CancellationToken 取消讀寫。 錯誤處理適用場景Channel的類型創建Channel寫入和讀取消息使用場景示例代碼注…

基于Spring Boot的牙科診所管理系統的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

upload-labs-靶場(1-19關)通關攻略

文件上傳漏洞是指由于程序員再開發時&#xff0c;未對用戶上傳的文件進行嚴格的驗證和過濾&#xff0c;而導致用戶可以上傳可執行的動態腳本文件 Pass-01&#xff08;前端驗證繞過&#xff09; 上傳111.php文件&#xff0c;發現彈窗顯示不允許&#xff0c;并給出白名單文件類…

使用 pytesseract 進行 OCR 識別:以固定區域經緯度提取為例

引言 在智能交通、地圖定位等應用場景中&#xff0c;經常會遇到需要從圖像中提取經緯度信息的需求。本篇文章將介紹如何利用 Python 的 pytesseract 庫結合 PIL 對圖像進行預處理&#xff0c;通過固定區域裁剪&#xff0c;來有效地識別出圖像上顯示的經緯度信息。 1. OCR 與 …

docker安裝和卸載

服務器系統&#xff1a;Ubuntu Server 18.04.2 64bit 1 安裝docker&#xff1a; 1.1 在線安裝 1.# yum install docker 1.2 離線安裝 https://download.csdn.net/download/qq_27106141/90477700 1.# docker-18.03.1-ce.tgz 1.2.1 解壓 tar -xzvf docker-18.03.1-ce.tgz 1.2.2…