資料庫正規化實踐 權衡一致性與讀取效能,打造高品質儲存

me
林彥成
2023-09-28 | 4 min.
文章目錄
  1. 1. 什麼是資料庫的組織與正規化?
  2. 2. 正規化
  3. 3. 反正規化
  4. 4. Single Table Design
  5. 5. 資料收納的選擇
  6. 6. FAQ:資料庫組織常見問題
    1. 6.1. Q1:什麼時候應該停止正規化 (Stop Normalizing)?
    2. 6.2. Q2:Single Table Design 只適用於 DynamoDB 等 NoSQL 嗎?
    3. 6.3. Q3:反正規化會導致資料不一致嗎?該如何預防?

什麼是資料庫的組織與正規化?

資料庫正規化 (Database Normalization) 是一種系統性的資料組織過程,旨在減少資料冗餘並確保資料一致性。其核心在於透過「欄位原子化」將複雜資料拆解為不可再分的最小單位,並透過建立資料表間的關聯來管理資訊。然而,極致的組織往往伴隨著複雜的查詢成本(Join 效能損耗);因此,在需要極高讀取效能或擴展性的場景下,開發者會採用 反正規化 (Denormalization)Single Table Design。這類技術權衡了儲存空間與一致性,以換取更快的查詢速度與更靈活的資料結構,是構建大規模 Web 應用程式不可或缺的架構智慧。


不知道大家有沒有過這樣的經驗,每次參加求活動拿到很多造型很醜的贈品,明明沒花錢買但又覺得丟掉或送人都怪怪的,沒花錢卻出現浪費跟可惜的感覺,久而久之房間就堆放許多雞肋但沒有用到的物品。

當物品被堆疊後就很容易被遺忘,當需要時又需要翻箱倒櫃去找,這就跟丟垃圾桶沒什麼區別。

你是否問過自己擁有什麼?
為了要擁有那些付出什麼?
追逐的人生換來那些什麼?
最後能帶走什麼?
—— 五月天 What A Song

物品在經過選擇後而沒有辦法馬上拋棄的話,收納就會是重要的,收納能夠讓我們輕鬆地找到需要的東西,而不必花時間一層一層地尋找或者堆疊物品,接下來就讓我們從資料儲存的角度切入來看看收納的概念。

正規化

正規化(Normalization)要求將資料分散到不同的表格中,目的是確保資料的一致性、減少重複性,目標在提高資料管理的效率,但可能會導致複雜的查詢。

資料庫的過度正規化就像是極致的收納,然而極致收納可能導致在使用介面(UI)時變得不方便,因為 UI 通常需要將資料全部展示出來,這代表可能需要不斷地把櫃子的東西倒出來排好然後又把東西一層一層塞回去容量有限的抽屜關起來。

但欄位的原子化仍舊相當的重要,也就是讓欄位的值不能進一步分解,這有助於確保資料的單一性和結構的簡單性。

例如如果有一個名稱欄位,不應該包含姓名、姓氏,而應該將它們分開儲存。

姓名課程
小明“數學,物理(二),化學(一)”
小華“英文,物理(一),化學(二)”

姓名: “小明,小華”
課程: “數學,物理(二),化學(一)”

正規化會把課程內容再原子化分為兩個欄位
課程名稱: “數學,物理,化學”
課程代號: “一,二”

如果現在要找出所有化學課:

  • 有符合原子化的 query: select * from 課程列表 where course_name = '物理'
  • 沒符合原子化的 query: select * from 課程列表 where course like '化學%'

以上面的例子來說,原子化後可以看出效能的差異,但正規化再繼續做下去,多對多的關係再拆分就會需要更多資料表,當資料筆數變更多查詢的效能就會越差。

反正規化

反正規化 (Denormalization) 可以將相關資料合併到一個表中,以減少查詢的複雜性,從而提高讀取效能,但可能會增加資料冗餘和管理複雜性。

為了效能的反正規化,雖然沒遵守 3NF 但也需要仔細的設計和規劃,該做的原子化還是建議要做,不適當的使用可能會導致效能問題或資料管理上的困難。

Single Table Design

是一種資料庫設計方法,它將所有不同種類的資料都存儲在一個資料表中,這種設計方法強調簡單性和可擴展性,特別適用於 NoSQL 資料庫。

  • 易於擴展: 資料無需在不同的表之間移動或轉換資料,可以輕鬆處理不斷增長的資料量。
  • 靈活性: 不要求資料具有相同的結構。
  • 簡化查詢: 單個表可簡化查詢操作,無需不同的表或進行複雜的資料處理。
  • 高效性能: 適合高度分散式的設計來達到極高的性能。
  • 簡化管理: 管理一個表比多個表更容易。

資料收納的選擇

在資料庫設計中需要仔細考慮應用的需求和性能要求:

  • 正規化:通常用於需要高度資料一致性,例如金融系統或醫療記錄。
  • 反正規化:通常用於需要快速查詢和報告,例如分析或報告工具。
  • Single Table Design:通常用於需要擴展性和簡單性的應用,例如大規模 Web 應用或物聯網設備。

最終的選擇應該基於實際的情況,需要權衡資料一致性、性能和管理複雜性,實作上也可以混合使用這些解決方案,以滿足不同類型的資料和查詢需求。


FAQ:資料庫組織常見問題

Q1:什麼時候應該停止正規化 (Stop Normalizing)?

A:當您發現為了讀取一個頁面的資料需要 Join 超過 5 個以上的資料表,且導致明顯的效能下降時,就應該考慮停止正規化。在「開發者理解成本」與「機器運算效能」之間取得平衡是關鍵,有時候適度的冗餘(Redundancy)是為了系統的強韌性。

Q2:Single Table Design 只適用於 DynamoDB 等 NoSQL 嗎?

A:雖然 Single Table Design 在 NoSQL 社群非常流行,但其核心概念(將異質資料扁平化)也可以應用在關聯式資料庫中(如使用 JSONB 欄位)。重點在於減少跨表連結的次數,並透過精確的索引設計來加速特定模式的查詢。

Q3:反正規化會導致資料不一致嗎?該如何預防?

A:會。 這是反正規化最大的風險。預防機制通常包括:1. 透過應用程式邏輯(Application Logic)確保更新時同步異動多處資料;2. 使用資料庫觸發器(Triggers);或 3. 接受「最終一致性 (Eventual Consistency)」,透過背景排程定期修復偏差資料。


資料的收納是一場永無止境的權衡。掌握正規化的嚴謹與反正規化的靈活,讓您的系統在面對海量數據時依然能優雅擴展,輕鬆早下班!


喜歡這篇文章,請幫忙拍拍手喔 🤣