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

MySQL WHERE 子句優化機制深度解析:從括號消除到索引選擇

     編輯:MySQL 資料庫相關知識

MySQL 查詢優化器對 WHERE 條件有一套自動改寫與裁剪規則。理解這些規則,能幫你寫出更易優化的 SQL,也能看懂 EXPLAIN 的執行計畫。

優化器自動改寫規則

1. 消除冗餘括號

((a AND b) AND c OR (((a AND b) AND (c AND d))))
-- 簡化為
(a AND b AND c) OR (a AND b AND c AND d)

2. 常數傳播

(a < b AND b = c) AND a = 5
-- 推導為
b > 5 AND b = c AND a = 5

3. 移除恆真/恆假條件

(B >= 5 AND B = 5) OR (B = 6 AND 5 = 5) OR (B = 7 AND 5 = 6)
-- 簡化為
B = 5 OR B = 6

4. 常數表達式只算一次

WHERE id > 100 + 200 → 優化器直接當成 id > 300。

特殊快速路徑

  • COUNT(*) 無 WHERE 直接從表元資料讀取(MyISAM)或掃描最小索引(InnoDB)。
  • 單表 NOT NULL 欄位同理可快速統計。
  • 早期偵測不可能條件:WHERE 1=0 直接返回空結果,不掃表。
  • HAVING 無 GROUP BY 時自動合併為 WHERE。

常數表優先讀取

優化器識別「常數表」(空表、單行表、唯一索引等值查詢),優先讀取並將其值視為常數代入後續聯結,大幅縮小搜尋空間。

-- 範例:t1 主鍵=1 為常數表
SELECT * FROM t1, t2 WHERE t1.pk = 1 AND t2.fk = t1.id;

聯結順序與臨時表

  • 嘗試所有聯結順序組合,選擇成本最低者。
  • ORDER BY/GROUP BY 欄位來自同一表 → 該表優先驅動。
  • SQL_SMALL_RESULT → 強制用記憶體臨時表而非排序。
  • DISTINCT + ORDER BY 常觸發臨時表。

索引使用門檻

  • 預估掃描行數 < 30% 總行數 → 使用索引。
  • 否則改全表掃描(Sequential Scan)更快。
  • 覆蓋索引:SELECT 只涉及索引欄位 → 只讀索引樹,不回表。

極速查詢模式範例

模式SQL 範例優化點
單值聚合SELECT COUNT(*) FROM tbl直接讀元資料
索引區間極值SELECT MIN(k1),MAX(k1) FROM tbl只走索引樹左右最深節點
前綴等值+極值SELECT MAX(k2) FROM tbl WHERE k1=const索引 (k1,k2) 直接定位
排序+限制SELECT * FROM tbl ORDER BY k1,k2 LIMIT 10索引順序掃描停早
覆蓋索引查詢SELECT k1,k2 FROM tbl WHERE k1=val不回表,極快
索引分組SELECT k2 FROM tbl GROUP BY k1索引順序天然分組

排序優化

ORDER BY key_part1, key_part2 若符合索引順序(或倒序 DESC),可省略 filesort,直接按索引輸出。

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