同樣邏輯的 SQL,寫法不同效能可差百倍。本文從資料型別、字符集、聚合函數、子查詢、集合運算五個維度,給出可落地的優化法則與避坑指南。
IS NULL)NOT NULL,必要時用 0、-1、'' 作為語意預設值TINYINT (1B) vs INT (4B),CHAR(10) vs VARCHAR(255)ALTER TABLE 修改型別會重建表、鎖表、風險大CONVERT() 消耗 CPUUTF-8/utf8mb4 多位元組佔用更多空間,規劃長度時乘 3~4utf8mb4,避免轉換開銷| 場景 | MyISAM | InnoDB |
|---|---|---|
| 無 WHERE | 極快(儲存行數) | 全表掃描(MVCC 可見性檢查) |
| WHERE 命中索引 | 索引掃描計數 | 索引掃描計數 |
| WHERE 未命中索引 | 全表掃描 | 全表掃描 |
summary_table,查詢 O(1)WHERE 欄位 + COUNT 欄位建立複合索引,避免回表MySQL 優化器對子查詢(特別是 IN (SELECT...))處理較弱,常退化為全表掃描 + 臨時表。
-- 原:子查詢
SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2 WHERE status = 1);
-- 優化:JOIN
SELECT t1.* FROM t1
JOIN t2 ON t1.id = t2.t1_id
WHERE t2.status = 1;
t2)連線欄位必須有索引t1)通常全表掃描,配合 LIMIT 或條件下推WITH) 可讀性更好,效能相當UNION = UNION DISTINCT,需排序去重,大表極慢。
| 方案 | 適用條件 | 效能增益 |
|---|---|---|
UNION ALL | 業務確定無重複、或可容忍重複 | 免排序,速度提升 10x+ |
| 應用層去重 | 結果集較小、邏輯複雜 | 避免資料庫排序 |
| 分頁查詢改寫 | 兩張表分頁合併 | 各自 LIMIT 再 UNION ALL |
(SELECT * FROM blog WHERE top = 1 ORDER BY created DESC)
UNION ALL
(SELECT * FROM blog WHERE top = 0 ORDER BY created DESC)
LIMIT 2, 3;
slow_query_log,定期分析 Top 10 慢查詢EXPLAIN 驗證執行計畫,關注 type、key、rows、Extra優化無終點,但有法則。掌握五大法則,建立度量體系,持續迭代。