數據庫是信息系統核心,SELECT 語句佔比最高且代價最大。百萬級數據全表掃描耗時數分鐘至數小時,優秀的查詢計劃可將耗時壓縮至秒級。優化器雖智能,但SQL 編寫質量是優化上限——糟糕的 SQL 無法靠優化器變高效。
用戶 SQL 是優化器的輸入原料,編寫高效 SQL 是開發者核心責任。
ANALYZE TABLE 更新統計信息;大量寫入後 OPTIMIZE TABLE 或重建索引消除碎片。ORDER BY/GROUP BY,避免 Filesort。OR 條件拆分為 UNION(各分支可用索引),例如:SELECT * FROM orders WHERE (cust=104 AND ord>1001) OR ord=1008SELECT * FROM orders WHERE cust=104 AND ord>1001 UNION SELECT * FROM orders WHERE ord=1008JOIN、EXISTS、IN 或應用層分步查詢。LIMIT、高選擇性 WHERE)。LIKE 'prefix%' 可用索引;LIKE '%suffix'、LIKE '%mid%' 全表掃描。zipcode LIKE '98___' → zipcode BETWEEN '98000' AND '98999'。SUBSTRING(col,2,3))不可用索引,考慮全文索引或 Elasticsearch。-- 將高頻複雜查詢結果物化
CREATE TEMPORARY TABLE tmp_cust_balance AS
SELECT c.name, r.balance, ...
FROM cust c JOIN rcvbles r ON c.id=r.cust_id
WHERE r.balance>0 AND c.postcode>'98000'
ORDER BY c.name;
-- 後續多維分析直接查詢臨時表
SELECT * FROM tmp_cust_balance WHERE region='East';
注意:臨時表不自動同步主表變更,高寫入場景需定時重建或改用物化視圖(MySQL 8.0+ 支援)。
隨機磁盤讀取(磁頭跳躍)極慢。將大量隨機點查改為批量排序後順序讀,可將 I/O 降低數量級。典型場景:大批量 ID 查詢 → 先排序 ID → 單次範圍掃描。
EXPLAIN SELECT * FROM orders WHERE customer_id=1001 AND amount>500;
| 列 | 關鍵值含義 | 優化目標 |
|---|---|---|
| type | ALL/index/range/ref/eq_ref/const/system | 避免 ALL,力求 ref/range/const |
| key | 實際使用的索引 | 無 key → 需建立索引 |
| key_len | 索引使用長度 | 複合索引是否最左前綴生效 |
| rows | 預估掃描行數 | 越小越好 |
| Extra | Using where/Using index/Using temporary/Using filesort | 避免 temporary/filesort;Using index 為覆蓋索引 |
MySQL 查詢優化是系統工程:索引設計是基石,SQL 改寫是手段,架構演進是終局。建立 EXPLAIN 審查機制,將慢查詢日誌(long_query_time=1)納入日常巡檢,持續迭代優化,才能支撐業務高速增長。