開發反饋某視圖 SELECT 需要 1987 秒(33 分鐘),返回 21068 行。EXPLAIN 顯示 Using filesort,排序開銷極大。
初步嘗試優化 WHERE 後的子判斷,將 SELECT MAX(ol2.ID) 等改寫,但效果微乎其微。
視圖定義中存在多層嵌套子查詢 + 不必要的排序,導致優化器無法下推條件,被迫全量掃描後文件排序。
CREATE ALGORITHM=UNDEFINED
SQL SECURITY DEFINER
VIEW view_offer_label AS
SELECT
ol.OFFER_ID,
ol.EFFECTIVE_DATE,
...
FROM offer_label ol
JOIN (
SELECT offer_id, MAX(id) AS max_id
FROM offer_label_history
GROUP BY offer_id
) olh ON ol.OFFER_ID = olh.offer_id
WHERE ol.STATUS = 1
AND ol.EFFECTIVE_DATE <= NOW();
關鍵改動:
ORDER BY,交由外層應用按需排序。INDEX idx_status_date (STATUS, EFFECTIVE_DATE)。21068 rows in set (0.08 sec)
性能提升 24,837 倍,從「跑報表喝杯咖啡」到「毫秒級響應」。
Using filesort、Using temporary、Derived table 關鍵字。| 反模式 | 後果 | 修正 |
|---|---|---|
| 視圖內 ORDER BY | 強制全量排序,殺死分頁查詢 | 移至應用層或外層查詢 |
| 多層視圖嵌套 | 優化器無法合併,產生臨時表 | 扁平化為單層視圖或 CTE |
| 視圖含聚合函數 | 不可更新,且阻礙條件下推 | 改用物化表/匯總表定時刷新 |
| 缺少覆蓋索引 | 回表/全掃描 | 按 WHERE/JOIN/ORDER 列建組合索引 |
視圖是邏輯封裝層,不是性能免死金牌。複雜視圖必須像對待核心 SQL 一樣嚴格 Review、EXPLAIN、壓測。這次優化,0 行業務代碼變更,僅重構視圖定義,即獲數萬倍收益——這就是數據庫治理的杠桿效應。