沒有最佳解,你必須通盤了解,才能找到最適解!

本文大綱

正規化

最近在寫程式時,常面臨到 database join 來 join 去,導致於執行速度過慢,開發時,又要理解很多 table 之間的關聯,正規化真的好嗎?

當你不知道選擇哪個架構,往往是你不清楚你想要什麼?

正規化要解決的事情是降低資料的重複性,你不會在一個 table 裡面看到 訂單資料使用者資料,這樣這張表就太多 column,一個視窗也拉不完,因此會將 訂單資料 成一個獨立的表, 使用者資料 成另一個獨立表,可避免資料重複。

正規化的優點:

  1. 降低資料的重複性
  2. 去除相依性,利用外部索引鍵,產生關聯
  3. update 資料較快(因 update 部分資料,例如:只想更新使用者地址,那就更新使用者資料,不必更新訂單的每個資料)

正規化的缺點:

  1. 耦合性高,牽一髮動全身(約束性強)
  2. 查詢較慢(如 join table 到一定數量,爆炸慢)
  3. DB I/O 繁忙,因為 join 很多表
  4. 儲存成本高

正規化細節

  1. 第一正規化:去除重複性,像是購物車訂單,不會包含此筆訂單下的所有商品,不會存成…

    錯誤示範 cart_orders

    id user product
    1 jamie 麥片、水果
    2 win 水果、滑鼠
    3 leo 滑鼠、麥片

    應該會存成下面這樣,才會是模範生…

    正確示範 cart_orders

    id user product
    1 jamie 麥片
    2 jamie 水果
    3 win 水果
    4 win 滑鼠
    5 leo 滑鼠
    6 leo 麥片

  2. 第二正規化:去除相依性,使用外部索引鍵,讓這些資料表產生關聯,而不是一張 table 塞入所有資訊
    不要以為剛剛那樣就很完美,還有一些地方可以優化,仔細看下面示範,把 userproduct 放在同一張表內

    錯誤示範 cart_orders

    id user product
    1 jamie 麥片
    2 jamie 水果
    3 win 水果
    4 win 滑鼠
    5 leo 滑鼠
    6 leo 麥片

    應該要分成兩張表 userscart_orders

    正確示範 cart_orders

    id user_id product
    1 1 麥片
    2 1 水果
    3 2 水果
    4 2 滑鼠
    5 3 滑鼠
    6 3 麥片

    正確示範 users

    id name
    1 jamie
    2 win
    3 leo

  3. 第三正規化:刪除不依賴索引鍵的欄位,例如說:訂單數量 count 與單價 unit_price 已經存在表單,又多了每一筆訂單的 amount,就是不必要的
    因此,剛剛的 schema 還可以優化,例如說以下錯誤示範

    錯誤示範 cart_orders

    id user_id product count unit_price amount
    1 1 麥片 2 2 4
    2 1 水果 3 1 3
    3 2 水果 4 1 4
    4 2 滑鼠 1 10 10
    5 3 滑鼠 7 10 70
    6 3 麥片 10 2 20

    應該要把相依性 amount 拿掉

    正確示範 cart_orders

    id user_id product count unit_price
    1 1 麥片 2 2
    2 1 水果 3 1
    3 2 水果 4 1
    4 2 滑鼠 1 10
    5 3 滑鼠 7 10
    6 3 麥片 10 2

什麼時候反正規化

教科學經常告訴學生最好的參照方式,但實際運用時必須考慮天時、地利、人和,簡單說,就是必須考量到實際運用情境。 當你遇到商業邏輯極為複雜時,又使得資料庫正規化到極致,很有可能讓後續維護困難
以下幾種情境可以使用反正規化

  1. 耦合性高,牽一髮動全身(約束性強)
  2. 經常要查詢,但不常更動的設計(因為常查詢如果反正規化可以少 join 一堆 table)
  3. 資料不超過百萬
  4. 不要求快速寫入

學習重點

這一次要重整公司複雜的商業邏輯,因過去時空背景下,是將資料正規化到極致,導致於後續維護成本高,因此尋找有沒有更簡單的解法,
可以讓前人種樹,後人乘涼的解法,因此找到了反正規化,因此寫了兩者的比較,讓自己對 database schema 設計更了解,才能設計出更好的架構。

可以簡單,何必複雜!

參考連結