優化目標:直擊資料庫效能瓶頸
- 減少 IO 次數:IO 是資料庫最大瓶頸,90% 以上時間消耗於 IO。優化首要任務是減少磁碟讀寫。
- 降低 CPU 計算:
ORDER BY、GROUP BY、DISTINCT 等操作屬 CPU 密集型,在 IO 優化到位後成為次要目標。
核心方法:改變執行計畫
SQL 優化的本質只有一個——改變 SQL 執行計畫,讓查詢「少走彎路」,透過索引等「捷徑」快速定位資料,達到減少 IO 與降低 CPU 的雙重效果。
常見誤區大揭密
❌ 誤區 1:count(1)/count(pk) 優於 count(*)
真相:MySQL 對 count(*) 有專門優化,某些場景下反而更快。count(column) 統計的是該欄位非 NULL 的筆數,與 count(*) 語意完全不同。
❌ 誤區 2:select 少欄位就能減少 IO
真相:大多數關聯式資料庫採行式儲存,一個資料頁包含多行完整資料。除非查詢能完全在覆蓋索引內完成(避免回表),否則欄位多寡不影響 IO 量。
❌ 誤區 3:ORDER BY 一定會排序
真相:若資料順序與索引順序一致且走該索引,MySQL 會省略排序直接回傳。善用索引優化排序是關鍵技巧。
❌ 誤區 4:Explain 出現 filesort 代表磁碟排序
真相:Using filesort 只是表示需排序操作,不代表一定落盤。記憶體排序同樣會顯示此標記。
SQL 撰寫基本原則
- 盡量少 JOIN:MySQL 優化器在多表 JOIN 表現不如 Oracle,單表查詢效能最佳。
- 盡量少排序:利用索引順序、減少參與排序筆數、非必要不排序。
- 避免 SELECT *:配合 ORDER BY 時欄位數影響排序效率;覆蓋索引場景下能大幅減少 IO。
- 以 JOIN 取代子查詢:MySQL 子查詢執行計畫長期存在效能問題。
- 盡量少用 OR:
WHERE 子句中大量 OR 導致優化器失效,改用 UNION ALL。
- 用 UNION ALL 取代 UNION:UNION 需去重排序,UNION ALL 直接合併,效能差異巨大。
- 盡早過濾:先在單表過濾分頁再 JOIN,大幅減少不必要 IO。
- 避免隱性型別轉換:
WHERE 子句欄位與參數型別不一致會導致索引失效,應在參數端轉型。
- 優先優化高併發 SQL:高併發慢查詢摧毀性遠大於低頻大查詢。
- 全局視野優化:調整索引時顧及所有 SQL,避免因小失大。
- 對每條 SQL 執行 EXPLAIN:掌握執行計畫才能判斷優化空間與問題。
延伸閱讀建議
- MySQL ORDER BY 實現分析
- MySQL GROUP BY 基本實現原理
- MySQL DISTINCT 基本實現原理
- 理解 Explain 輸出中的 filesort