首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 子查詢效能陷阱:從 1 小時優化到 1.1 秒的實戰復盤

     編輯:MySQL 綜合教學

MySQL 子查詢效能陷阱:從 1 小時優化到 1.1 秒的實戰復盤

同一個業務需求,寫法不同,效能相差 3000 倍。本文透過「每類別最小值」查詢案例,揭示相關子查詢與分組聚合的本質差異。

業務需求

表 my_tbl(a, b, c),查詢每個 a 值下 b 為最小值的完整記錄。
樣本數據 80 萬行,期望結果:

a  b  c
1  3  'cd'
2  3  'nhd'
3  7  'vsd'

方案一:相關子查詢(災難)

SELECT A.* FROM my_tbl AS A 
WHERE A.b = (SELECT MIN(b) FROM my_tbl AS B WHERE B.a = A.a);

執行 1 小時未出結果。 原因:外層 80 萬行,每行觸發一次子查詢,內層需掃描同組數據,複雜度 O(N²),且無法利用索引下推。

方案二:分組聚合 + 連接(1.1 秒)

SELECT a, b, c, COUNT(a) 
FROM (
    SELECT a, b, c FROM my_tbl GROUP BY a, b
) AS A 
GROUP BY a;

邏輯:先按 (a, b) 分組 → 每組取第一行(因按 b 升序,即最小 b)→ 外層按 a 再分組取首行。
優化器可使用 INDEX (a, b) 完成 Loose Index Scan,僅掃描各組首行。

核心差異對比

維度相關子查詢分組聚合
執行模式逐行嵌套循環單次掃描 + 流式聚合
索引利用難以利用複合索引可觸發 Loose Index Scan
複雜度O(N × GroupSize)O(N) 或 O(GroupCount)
80萬行耗時> 3600 秒1.1 秒

最佳實踐建議

  1. 需「每組 Top-N」時,優先考慮 ROW_NUMBER() OVER (PARTITION BY ...)(MySQL 8.0+)
  2. MySQL 5.7 可用 GROUP BY 技巧或用戶變量模擬
  3. 避免在 WHERE 子句中對大表使用相關子查詢
  4. 關鍵欄位建立複合索引 (a, b) 支援分組掃描

延伸閱讀

更多 MySQL 進階技巧請參考專題:《MySQL 事務操作技巧匯總》、《MySQL 存儲過程技巧大全》、《MySQL 數據庫鎖相關技巧匯總》及《MySQL 常用函數大匯總》。

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