數據庫設計的三大範式

2020-08-08 14:48:37
爲了建立冗餘較小、結構合理的數據庫,設計數據庫時必須遵循一定的規則。在關係型數據庫中,這種規則就是範式。範式是符合某一種級別的關係模式的集合。關係型數據庫中的關係必須滿足一定的要求,即滿足不同的範式。、

目前關係型數據庫有六種範式,分別爲:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、第四範式(4NF)、第五範式(5NF)和第六範式(6NF)。要求最低的範式是第一範式。第二範式在第一範式的基礎上又進一步的新增了要求,其餘範式依次類推。

一般說來,數據庫只需滿足第三範式就行了,而通常我們用的最多的就是第一範式、第二範式、第三範式,也就是接下來要講的“三大範式”。

1)第一範式

第一範式(1NF)用來確保每列的原子性,要求每列(或者每個屬性值)都是不可再分的最小數據單元(也稱爲最小的原子單元)。

例如,客人住宿資訊表 (姓名, 客人編號, 地址, 客房號, 客房描述, 客房型別, 客房狀態, 牀位數, 入住人數, 價格)。

其中,“地址”列還可以細分爲國家、省、市、區等,甚至有的程式還把“姓名”列也拆分爲“姓”和“名”等。如果業務需求中不需要拆分“地址”和“姓名”列,則該數據表符合第一範式,如果需要將“地址”列拆分,則下列寫法符合第一範式:

客人住宿資訊表(姓名, 客人編號, 國家, 省, 市, 區, 門牌號, 客房號, 客房描述, 客房型別, 客房狀態, 牀位數, 入住人數, 價格)。

2)第二範式

第二範式(2NF)在第一範式的基礎上更進一層,要求表中的每列都和主鍵相關,即要求實體的唯一性。如果一個表滿足第一範式,並且除了主鍵以外的其他列全部都依賴於該主鍵,那麼該表滿足第二範式。

客人住宿資訊表中的數據主要用來描述客人住宿資訊,所以該表主鍵爲(客人編號,客房號):
  • “姓名”列、“地址”列➡“客人編號”列。
  • “客房描述”列、 “客房型別”列、“客房狀態”列、“牀位數”列、“入住人數”列、“價格”列➡“客房號”列。

其中,“➡”符號代表依賴。以上各列沒有全部依賴於主鍵(客人編號,客房號),只是部分依賴於主鍵,不符合第二範式。

使用第二範式後,客人住宿資訊表可以分解成以下兩個表:
  • 客人資訊表(客人編號,姓名,地址,客房號,入住時間,結賬日期,押金,總金額),主鍵爲“客人編號”列,其他列都全部依賴於主鍵列。
  • 客房資訊表(客房號,客房描述,客房型別,客房狀態,牀位數,入住人數,價格),主鍵爲“客房號”列,其他列都全部依賴於主鍵列。

3)第三範式

第三範式(3NF)在第二範式的基礎上更進一層,第三範式是確保每列都和主鍵列直接相關,而不是間接相關,即限制列的冗餘性。如果一個關係滿足第二範式,並且除了主鍵以外的其他列都依賴於主鍵列,列和列之間不存在相互依賴關係,則滿足第三範式。

爲了更好的理解第三範式,這裏我們需要瞭解傳遞依賴。假設A、B 和 C 是關係 R 的三個屬性,如果 A➡B 且 B➡C,則從這些函數依賴中,可以得出 A➡C。如上所述,依賴 A➡C 稱之爲傳遞依賴。

以第二範式中的客房資訊表爲例,初看該表時沒有問題,滿足第三範式,每列都和主鍵列“客房號”相關,再細看會發現:
  • "牀位數” 列、“價格”列➡“客房型別”列。
  • “客房型別”列➡“客房號”列。
  • “牀位數”列、“價格”列➡“客房號”列

爲了滿足第三範式,應該去掉“牀位數”列,“價格”列和“客房型別”列,將客房資訊表分解爲如下兩個表。
  • 客房表(客房號,客房描述,客房型別編號,客房狀態,入住人數)
  • 客房型別表(客房型別編號,客房型別名稱,牀位數,價格)

主鍵與外來鍵在多表中的重複出現不屬於數據冗餘,非鍵欄位的重複出現纔是數據冗餘。在客房表中客房狀態存在冗餘,需要進行規範化,規範化以後的表如下:
  • 客房表(客房號,客房描述,客房型別編號,客房狀態編號,入住人數)。
  • 客房狀態表(客房狀態編號,客房狀態名稱)

4)反範式化

不滿足範式的數據庫設計,就是反範式化。

範式化可以設計出沒有冗餘的數據庫,但是並不是所有不冗餘的數據庫都是好數據庫。有時爲了提高數據庫效能,就必須降低範式標準,適當的保留冗餘數據。通俗的說,降低範式就是增加欄位,允許冗餘,達到以空間換時間的目的。

比如,有一張存放商品的基本表,數據表中包括“單價”、“數量”“金額”等欄位。“金額”這個欄位就說明該表的設計不滿足第三範式,因爲“金額”可以由“單價”乘以“數量”得到,說明“金額”是冗餘欄位。但是,增加“金額”這個冗餘欄位,可以提高查詢統計的速度,這就是以空間換時間的做法。

優缺點

最後我們來總結一下範式化和反範式化的優缺點。

1)範式化

優點如下:
  • 減少數據冗餘
  • 範式化後的表中只有很少的重複數據,更新時只需要更新較少的數據,所以範式化的更新操作比反範式化更快
  • 範式化的表通常比反範式化更小

缺點如下:
  • 範式化的表在查詢時經常需要很多的關聯,這回導致效能降低
  • 增加了索引優化的難度

2)反範式化

優點如下:
  • 可以減少表的關聯
  • 可以更好的進行索引優化

缺點如下:
  • 數據表存在數據冗餘及數據維護異常
  • 對數據的修改需要更多的成本