SQL 優化的本質只有一個:**改變執行計劃,讓查詢走捷徑**。本文確立「減少 IO、降低 CPU」雙目標,揭露 5 大常見誤區,制定 11 條優化鐵律,並深度解析 COUNT、SELECT *、ORDER BY、JOIN、子查詢、OR、UNION 等關鍵點優化策略。
唯一手段:改變 SQL 執行計劃(Execution Plan)。
| 誤區 | 真相 |
|---|---|
| count(1)/count(pk) 優於 count(*) | MySQL 對 count(*) 有特殊優化,某些場景 count(*) 更快。 |
| count(col) = count(*) | count(col) 統計非 NULL 行數;count(*) 統計總行數,語義與執行邏輯完全不同。 |
| select 少列 = 讀少數據 | 行存儲下,整行讀入內存;僅當覆蓋索引時少列才減少 IO。 |
| ORDER BY 必然排序 | 若利用索引有序性,優化器可省略排序操作(Extra 無 Using filesort)。 |
| Explain 顯示 Using filesort = 磁盤排序 | 只要需排序必顯示 Using filesort,不代表一定落盤;內存排序也顯示此標記。 |
UNION ALL 分開查詢合併。COUNT(*) 走聚簇索引掃描,並行讀取。-- 僅查詢索引包含的列,避免回表 SELECT id, name FROM users WHERE status=1; -- 若有 idx_status_name(id, name, status) 可覆蓋
-- 索引 (a, b) 支持 ORDER BY a, b / ORDER BY a DESC, b DESC -- 不支持 ORDER BY a ASC, b DESC (混合排序) 或 ORDER BY b (非最左前綴)
-- 子查詢 SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2 WHERE cond); -- JOIN 改寫 SELECT t1.* FROM t1 JOIN t2 ON t1.id = t2.t1_id WHERE t2.cond;
-- OR 可能全表掃描 SELECT * FROM t WHERE a=1 OR b=2; -- UNION ALL 走各自索引 SELECT * FROM t WHERE a=1 UNION ALL SELECT * FROM t WHERE b=2 AND a!=1; -- 避免重複
SQL 優化無銀彈,有的是對執行計劃的深度理解、對業務訪問模式的精準把控、對「全局視角」的堅守。將 11 條鐵律內化為代碼審查清單,配合持續的 EXPLAIN 審計,讓慢 SQL 無處遁形。