天天看點

阿裡華為P8級架構師教你MySQL資料庫設計三範式與反範式(下)4 三範式評價5 反範式(空間換時間)6 綜合案例

4 三範式評價

優點

  • 範式化的更新通常比反範式快
  • 當資料較好的範式化後,很少或者沒有備援資料
  • 範式化的資料比較小,放在記憶體中操作較快

缺點

  • 通常需要進行關聯

    畢竟阿裡規範提到

  • 阿裡華為P8級架構師教你MySQL資料庫設計三範式與反範式(下)4 三範式評價5 反範式(空間換時間)6 綜合案例

5 反範式(空間換時間)

反範式的過程就是通過适當的資料備援來提高查詢性能,但備援資料會犧牲資料一緻性。

  • 所有的資料都在同一張表中,可以減少表關聯
  • 更好進行索引優化

  • 存在大量備援資料
  • 資料維護成本更高(删除異常,插入異常,更新異常)

在企業中很好能做到嚴格意義上的範式成者反範式,一般需混合使用。

适當的資料備援

  • 被頻繁引用且隻能通過Join 2張(或者更多)大表的方式才能得到的小獨立字段
  • 這樣的場景由于每次Join僅僅隻是為了取得某個小字段的值,Join到的記錄又大,會造成大量不必要的lO,完全可以通過空間換取時間的方式來優化。

    不過,備援的同時需要確定資料的一緻性不會遭到破壞,確定更新的同時備援字段也被更新。

6 綜合案例

在一個網站執行個體中, 這個網站允許使用者發送消息,井且一些使用者是付費使用者。現在想檢視付費使用者最近的10條資訊。在user表 和message表中都存儲使用者類型(account type),而不用完全的反範式化。這避免了完全反範式化的插入和删除問題,因為即使沒有消息的時候也不會丢失使用者資訊。這樣也不會把user_message表搞得太大,有助高效擷取資料

另一個從父表備援些資料到子表的理由是排序的需要

緩存衍生值也是有用的。如果需要顯示每個使用者發了多少消息(類似論壇),可以每次執行一個昂貴的子查詢來計算并顯示它;也可以在user表中建個num_messages列,每當使用者發新消息時更新這個值。

範式設計

  • 使用者表

    使用者ID、姓名、電話、位址、郵箱

  • 訂單表

    訂單ID、使用者ID、下單時間、支付類型、訂單狀态

  • 訂單商品表

    訂單ID、商品 ID、商品價格

  • 商品表

    商品ID、名稱、描述、過期時間

SELECT b.使用者名, b.電話, b.位址, a.訂單ID,
       SUM(c.商品價價*C.商品數量) as 訂單價格
       // 上面這就需要三張表的關聯了,可能效率就很低了
FROM‘訂單表` a
JOIN‘使用者表’b ON a使用者ID=b.使用者ID
JOIN `訂單商品表` C ON c.訂單ID= b.訂單ID
GROUP BY b.使用者名,b.電話b.位址,a.訂單ID      

反範式設計

  • 訂單ID、使用者ID、下單時間、支付類型、訂單狀态、訂單價格、使用者名、電話、位址
  • 訂單ID、商品 ID、商品數量、商品價格
SELECT a.使用者名,a.電話.a.位址
,a.訂單ID
,a.訂單價格
FROM `訂單表` a      

把使用者表的位址加到了訂單表,這樣查詢位址時,就不需要把使用者表和訂單表關聯

參考

https://link.csdn.net/?target=https%3A%2F%2Fzh.wikipedia.org%2Fwiki%2F%25E7%25AC%25AC%25E4%25B8%2580%25E6%25AD%25A3%25E8%25A6%258F%25E5%258C%2596