3.4 · 反規範化
目標: 知道何時有意打破範式,並接受取捨。
反規範化是什麼
故意把冗餘引入規範化模式以加快讀取或簡化查詢 —— 通常通過存聚合值、去規範化查找或摘要。
為何反規範化
| 原因 | 例子 |
|---|---|
| 性能 | 日報需昂貴 JOIN;每小時存結果 |
| 報表 | OLAP / 資料倉庫層偏好寬表做分析 |
| 降低複雜性 | 前端查詢變簡單 |
| 快取 | 避免重算昂貴聚合 |
代價
| 取捨 | 詳情 |
|---|---|
| 更新異常 | 反規範副本可能漂離源頭 |
| 儲存 | 重複資料佔盤 |
| 維護 | 需觸發器 / 計劃任務保副本新 |
反規範化例子
例 1 · 在訂單上存顧客名快照
規範化:
Order(order_id, customer_id, …)
Customer(customer_id, name)1
2
2
要生成訂單收據就 JOIN 兩表。顧客改名後過去收據都顯示新名。
反規範化:
Order(order_id, customer_id, customer_name_at_order_time, …)1
利:收據總顯示當時名。弊:資料重複 —— 顧客修正筆誤,過去訂單仍顯筆誤。
例 2 · 預算每日總額
規範化:每次報告都從百萬行 Sales 算 SUM(sale_amount)。
反規範化:夜間任務填 DailyTotals(date, total_sales)。報告查這小表即時。
例 3 · 物化視圖(進階)
物化視圖是物理存的反規範快取;按計劃刷新。
反規範化步驟(要刻意做)
- 剖析慢查詢,確認規範化是瓶頸。
- 選能幫上忙的最小反規範化。
- 明確文件記冗餘。
- 加刷新策略(觸發器、任務、應用程式碼)。
- 監控漂移。
學生常見錯誤
- 規範化前先反規範化 —— 模式凌亂,理解不到取捨。
- 忘了把快取副本同步。
- 反規範化過度 —— 為微小收益複製一切。
考試式題目
題(5 分): 校報系統每次老師查班級總結都跑
Student、Class和 12 個月Score記錄的 JOIN。查詢慢了。(a) 建議反規範化方法。 (b) 討論方法的一個風險與一個緩解。
參考答案:
(a) 創建反規範化總結表:
sql
CREATE TABLE ClassSummary (
class_id VARCHAR(10),
month VARCHAR(7), -- '2026-06'
subject VARCHAR(30),
avg_score DECIMAL(5,2),
PRIMARY KEY (class_id, month, subject)
);1
2
3
4
5
6
7
2
3
4
5
6
7
夜間任務從 Student 與 Score 預聚合填此表。老師的「班級總結」視圖查這張小且帶索引的表。
(b) 風險:分數在夜間刷新後被改,則總結陳舊 —— 老師看到昨日數字而非今日。
緩解:分數改時立刻觸發更新總結;或在考試季更頻繁跑刷新任務(如每小時)。
關鍵要點
- 反規範化拿盤空間 + 複雜性換速度。
- 總用剖析證明合理。
- 預先規劃刷新策略。
➡️ 下一節:3.5 ER → 表