MySQL 內建 WHERE 優化規則
1. 條件簡化與常數傳播
- 移除多餘括號:
((a AND b) AND c) → (a AND b AND c)
- 常數摺疊:
(a5 AND b=c AND a=5
- 移除恆真/恆假條件:
(B>=5 AND B=5) → B=5
2. 索引使用策略
- 常數表優先讀取:空表、單行表、唯一索引查主鍵的表視為常數表。
- 最佳聯結順序:嘗試所有排列組合,若
ORDER BY/GROUP BY 欄位來自同一表,優先選該表驅動。
- 索引覆蓋:若查詢欄位皆在索引中 (且為數值型),僅掃描索引樹 (
Using index)。
- 範圍存取:
key_part1=val1 AND key_part2=val2 可用複合索引前綴。
3. 特殊查詢快速路徑
-- 直接從表資訊取得,無需掃描
SELECT COUNT(*) FROM tbl;
SELECT MIN(key), MAX(key) FROM tbl;
SELECT MAX(key2) FROM tbl WHERE key1=const;
-- 索引排序避免 filesort
SELECT * FROM tbl ORDER BY key1, key2 LIMIT 10;
SELECT * FROM tbl ORDER BY key1 DESC, key2 DESC LIMIT 10;
4. 子查詢與衍生表優化
- 每個子聯結構構建簡化 WHERE,盡早過濾行。
HAVING 無 GROUP BY 時合併至 WHERE。
DISTINCT 轉為 GROUP BY,可能產生臨時表。
實戰優化清單
- EXPLAIN 分析:關注
type (避免 ALL)、key (實際用到的索引)、rows (預估掃描行數)、Extra (Using where/Using index/Using filesort)。
- 避免隱含轉換:
WHERE varchar_col = 123 導致全表掃描,應寫 '123'。
- 善用複合索引:遵循最左前綴原則,
WHERE a=1 AND b=2 需索引 (a,b)。
- 範圍列放最後:
WHERE a=1 AND b>2 AND c=3 索引 (a,b,c) 只能用到 (a,b)。
- OR 條件拆分:
WHERE a=1 OR b=2 難用索引,改 UNION ALL。
參數調校
max_allowed_packet:大查詢/大欄位需調大。
sort_buffer_size / join_buffer_size:複雜排序/聯結調大。