5、数据库设计的三大范式
為了建立冗余較小、結構合理的數據庫,設計數據庫時必須遵循一定的規則。在關系型數據庫中,這種規則就是范式。范式是符合某一種級別的關系模式的集合。關系型數據庫中的關系必須滿足一定的要求,即滿足不同的范式。
目前關系型數據庫有六種范式,分別為:
第一范式(1NF)、
第二范式(2NF)、
第三范式(3NF)、
第四范式(4NF)、
第五范式(5NF)、
第六范式(6NF)。
要求最低的范式是第一范式。第二范式在第一范式的基礎上又進一步的添加了要求,其余范式依次類推。
一般說來,數據庫只需滿足第三范式就行了,而通常我們用的最多的就是第一范式、第二范式、第三范式,也就是接下來要講的“三大范式”。
1)第一范式
第一范式(1NF)用來確保每列的原子性,要求每列(或者每個屬性值)都是不可再分的最小數據單元(也稱為最小的原子單元)。
例如,客人住宿信息表 (姓名, 客人編號, 地址, 客房號, 客房描述, 客房類型, 客房狀態, 床位數, 入住人數, 價格)。
其中,“地址”列還可以細分為國家、省、市、區等,甚至有的程序還把“姓名”列也拆分為“姓”和“名”等。如果業務需求中不需要拆分“地址”和“姓名”列,則該數據表符合第一范式,如果需要將“地址”列拆分,則下列寫法符合第一范式:
客人住宿信息表(姓名, 客人編號, 國家, 省, 市, 區, 門牌號, 客房號, 客房描述, 客房類型, 客房狀態, 床位數, 入住人數, 價格)。
2)第二范式
第二范式(2NF)在第一范式的基礎上更進一層,要求表中的每列都和主鍵相關,即要求實體的唯一性。如果一個表滿足第一范式,并且除了主鍵以外的其他列全部都依賴于該主鍵,那么該表滿足第二范式。
客人住宿信息表中的數據主要用來描述客人住宿信息,所以該表主鍵為(客人編號,客房號):
- “姓名”列、“地址”列?“客人編號”列。
- “客房描述”列、 “客房類型”列、“客房狀態”列、“床位數”列、“入住人數”列、“價格”列?“客房號”列。
其中,“?”符號代表依賴。以上各列沒有全部依賴于主鍵(客人編號,客房號),只是部分依賴于主鍵,不符合第二范式。
使用第二范式后,客人住宿信息表可以分解成以下兩個表:
- 客人信息表(客人編號,姓名,地址,客房號,入住時間,結賬日期,押金,總金額),主鍵為“客人編號”列,其他列都全部依賴于主鍵列。
- 客房信息表(客房號,客房描述,客房類型,客房狀態,床位數,入住人數,價格),主鍵為“客房號”列,其他列都全部依賴于主鍵列。
3)第三范式
第三范式(3NF)在第二范式的基礎上更進一層,第三范式是確保每列都和主鍵列直接相關,而不是間接相關,即限制列的冗余性。如果一個關系滿足第二范式,并且除了主鍵以外的其他列都依賴于主鍵列,列和列之間不存在相互依賴關系,則滿足第三范式。
為了更好的理解第三范式,這里我們需要了解傳遞依賴。假設A、B 和 C 是關系 R 的三個屬性,如果 A?B 且 B?C,則從這些函數依賴中,可以得出 A?C。如上所述,依賴 A?C 稱之為傳遞依賴。
以第二范式中的客房信息表為例,初看該表時沒有問題,滿足第三范式,每列都和主鍵列“客房號”相關,再細看會發現:
- "床位數” 列、“價格”列?“客房類型”列。
- “客房類型”列?“客房號”列。
- “床位數”列、“價格”列?“客房號”列
為了滿足第三范式,應該去掉“床位數”列,“價格”列和“客房類型”列,將客房信息表分解為如下兩個表。
- 客房表(客房號,客房描述,客房類型編號,客房狀態,入住人數)
- 客房類型表(客房類型編號,客房類型名稱,床位數,價格)
主鍵與外鍵在多表中的重復出現不屬于數據冗余,非鍵字段的重復出現才是數據冗余。在客房表中客房狀態存在冗余,需要進行規范化,規范化以后的表如下:
- 客房表(客房號,客房描述,客房類型編號,客房狀態編號,入住人數)。
- 客房狀態表(客房狀態編號,客房狀態名稱)
最后,滿足三大范式的 E-R 圖如下所示:
滿足三大范式的數據庫模型圖如下所示:
4)反范式化
不滿足范式的數據庫設計,就是反范式化。
我們需要知道對于項目的最終用戶來說,用戶關心的是方便,清晰的數據結果。所以在設計數據庫時,設計人員和客戶在數據庫的設計規范化和性能之間會有一定的矛盾。
上面我們通過三大范式將客房表分解出兩個表,為了滿足客戶的需求,最終可能需要通過三個或四個表之間的連接查詢,來得到客戶需要的數據結果,插入數據同樣如此,對于客戶輸入的數據,我們需要分開插入到三個或四個不同的表中。
由此可以看出,為了滿足三大范式,我們的數據操作性能會受到相應的影響。
所以,在實際的數據庫設計中,既要考慮三大范式,避免數據的冗余和各種數據操作異常,又要考慮數據訪問性能。為了減少表連接,提高數據庫的訪問性能,也可以允許適當的數據冗余列,這也許就是最合適的數據庫設計方案。
比如,有一張存放商品的基本表,數據表中包括“單價”、“數量”“金額”等字段。“金額”這個字段就說明該表的設計不滿足第三范式,因為“金額”可以由“單價”乘以“數量”得到,說明“金額”是冗余字段。
與第三范式中介紹的冗余相比,前面介紹的冗余屬于低級冗余,我們反對低級冗余,但這里的冗余為高級冗余,目的是提高數據的處理速度,增加“金額”列后,可以提高查詢統計的速度,這是以空間換取時間的做法。
注意:不要輕易違反數據庫設計的規范化原則,如果處理不好,可能會適得其反,使應用程序運行速度更慢。
優缺點
最后我們來總結一下范式化和反范式化的優缺點。
1)范式化
優點如下:
- 減少數據冗余
- 范式化后的表中只有很少的重復數據,更新時只需要更新較少的數據,所以范式化的更新操作比反范式化更快
- 范式化的表通常比反范式化更小
缺點如下:
- 范式化的表在查詢時經常需要很多的關聯,這回導致性能降低
- 增加了索引優化的難度
2)反范式化
優點如下:
- 可以減少表的關聯
- 可以更好的進行索引優化
缺點如下:
- 數據表存在數據冗余及數據維護異常
- 對數據的修改需要更多的成本
總結
以上是生活随笔為你收集整理的5、数据库设计的三大范式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3、绘制E-R图:数据库概要设计阶段
- 下一篇: 6、数据库设计为什么要使用三大范式