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

MySQL 子查詢性能陷阱:從 1 小時到 1 秒,GROUP BY 替代關聯子查詢實戰

     編輯:MySQL 資料庫相關知識

場景:查每組最小值對應的完整行

表 my_tbl(a, b, c),需查每個 a 值下 b 最小的那行完整記錄。

-- 數據樣例
a | b | c
1 | 3 | 'cd'
2 | 3 | 'nhd'
1 | 5 | 'bg'
2 | 6 | 'cds'
1 | 7 | 'kiy'
3 | 7 | 'vsd'
3 | 8 | 'ndf'

-- 期望結果
a | b | c
1 | 3 | 'cd'
2 | 3 | 'nhd'
3 | 7 | 'vsd'

方案一:關聯子查詢(DEPENDENT SUBQUERY)—— 災難級

SELECT A.* FROM my_tbl AS A 
WHERE A.b = (SELECT MIN(b) FROM my_tbl AS B WHERE B.a = A.a);
  • EXPLAIN 顯示 DEPENDENT SUBQUERY
  • 外層全表掃描 80 萬行,**每行執行一次子查詢** → 80 萬次索引查找
  • **運行 1 小時未出結果**,強制終止

方案二:GROUP BY 分組取最小值 —— 秒級

SELECT a, b, c, COUNT(a) 
FROM (
    SELECT a, b, c FROM my_tbl GROUP BY a, b
) AS A 
GROUP BY a;
  • 內層 GROUP BY a, b 產生去重後的 (a,b,c) 組合
  • 外層 GROUP BY a 取每組第一行(MySQL 允許非聚合列任意取值,恰好是最小 b 對應的 c)
  • **執行 1.1 秒**,提速 3000+ 倍

原理對比

維度關聯子查詢GROUP BY 方案
執行模式逐行驅動(Nested Loop)集合運算(Hash/Stream Aggregate)
索引利用被動查找主動掃描+分組
臨時表無可能用到(但極快)
適用數據量極小(<1萬)百萬級無壓力

避坑指南

  1. 警惕 WHERE 列 = (SELECT 聚合 FROM 表 WHERE 關聯外層列) 模式,必產生 DEPENDENT SUBQUERY
  2. 優先考慮 GROUP BY / 窗口函數 (ROW_NUMBER) / JOIN 衍生表 替代關聯子查詢
  3. MySQL 8.0+ 窗口函數寫法(最標準):
    SELECT a, b, c FROM (
        SELECT a, b, c, ROW_NUMBER() OVER (PARTITION BY a ORDER BY b) AS rn
        FROM my_tbl
    ) t WHERE rn = 1;
  4. EXPLAIN 必看 select_type:DEPENDENT SUBQUERY = 高風險,SIMPLE/DERIVED = 相對安全

總結

**SQL 寫法決定執行策略,策略決定性能數量級差異**。將「逐行驅動」轉化為「集合運算」,是 SQL 優化的核心思維。養成 **寫完子查詢必看 EXPLAIN** 的習慣,讓性能問題止於開發階段。

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