首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 關聯子查詢優化:用 INNER JOIN 替代 EXISTS,從 2.4 秒降到 0.68 秒

     編輯:MySQL 資料庫相關知識

場景:EXISTS 關聯子查詢慢

SELECT * FROM table1 
WHERE EXISTS (
    SELECT * FROM table2 
    WHERE id >= 30000 AND table1.uuid = table2.uuid
);
  • table1:10 萬行
  • table2:100 萬行
  • 執行時間:**2.40 秒**
  • EXPLAIN:DEPENDENT SUBQUERY,外層全表掃描 table1,每行驅動子查詢

優化:改寫為 INNER JOIN

SELECT * FROM table1 
INNER JOIN table2 USING (uuid) 
WHERE table2.id >= 30000;
  • 執行時間:**0.68 秒**(提速 3.5 倍)
  • EXPLAIN:SIMPLE,優化器先過濾 table2.id >= 30000,再 Hash Join / Nested Loop

原理對比

維度EXISTS 關聯子查詢INNER JOIN
執行策略外層驅動,逐行查找優化器自由選擇連接順序/算法
過濾下推困難(子查詢內部過濾)自然下推(WHERE 直接作用於驅動表)
索引利用被動主動(可用 Hash Join / Batched Key Access)
結果集去重(EXISTS 語義)可能重複(需 DISTINCT 或業務保證唯一)

注意事項

  1. 語義差異: EXISTS 保證不重複,JOIN 可能產生笛卡爾積重複行。**若 table2.uuid 唯一或業務允許去重,安全替換**
  2. 不適用場景: 子查詢含聚合/窗口函數/非等值連接/外層多表關聯複雜邏輯
  3. MySQL 8.0+ 優化器 會自動將部分 EXISTS/IN 轉為 JOIN(subquery_to_derived/semijoin),但手工改寫更可控

驗證模板

-- 1. 原查詢 EXPLAIN
EXPLAIN SELECT ... EXISTS ...;

-- 2. 改寫 JOIN EXPLAIN
EXPLAIN SELECT ... INNER JOIN ...;

-- 3. 結果集對比(確認語義等價)
SELECT COUNT(*) FROM (原查詢) t1;
SELECT COUNT(DISTINCT uuid) FROM (JOIN查詢) t2;  -- 若一致,語義等價

總結

**關聯子查詢(EXISTS/IN)是優化器的盲區**,手工改寫為 **JOIN 讓優化器擁有完整統計信息、自由選擇最優路徑**。养成「見關聯子查詢,試 JOIN 改寫」的肌肉記憶,性能提升往往超預期。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved