在當前互聯網流行架構下,Redis、MongoDB等非關係型資料庫(NoSQL)正逐漸搶占更多的視野,然而正如其釋義(Not Only SQL)所說,NoSQL在當前仍然只作為傳統關係型資料庫的補充。當前的的大部分持久化場景下,關係型資料庫仍然占據不可替代的地位。因此,能夠設計出規範合理的關係數據表 ...
在當前互聯網流行架構下,Redis、MongoDB等非關係型資料庫(NoSQL)正逐漸搶占更多的視野,然而正如其釋義(Not Only SQL)所說,NoSQL在當前仍然只作為傳統關係型資料庫的補充。當前的的大部分持久化場景下,關係型資料庫仍然占據不可替代的地位。因此,能夠設計出規範合理的關係數據表也是所有後端程式員的必修功課,然而“規範合理”是否又有一個量化的指標呢?通常領域下答案是沒有,但在關係資料庫下還真的有,這就是我們常說的“資料庫範式”。
“來,你給翻譯翻譯,什麼叫範式?”
“不用翻譯,就是範式啊!”
“我讓你翻譯給我聽,什麼叫範式?”
“範式就是一種最佳實踐”
“翻譯翻譯,什麼叫**的範式?”
“範式就是一種前人經過無數次實踐與論證,得出的經驗總結!”
“我讓你翻譯翻譯,什麼**的叫**的範式?”
“你最好這麼乾,不然就是你錯了,得拉出去槍斃!”
“哦,原來這就是範式啊!”
說起資料庫範式,目前關係資料庫共有六種範式:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、巴斯-科德範式(BCNF)、第四範式(4NF)和第五範式(5NF,又稱完美範式),我們普遍認為達到第三範式就是較為合理的設計方案了,本篇文章也主要針對前三個範式做一個通俗解釋。
標準的三大範式定義:
第一範式:當關係模式R的所有屬性都不能在分解為更基本的數據單位時,稱R是滿足第一範式的,簡記為1NF。滿足第一範式是關係模式規範化的最低要求,否則,將有很多基本操作在這樣的關係模式中實現不了。
第二範式:如果關係模式R滿足第一範式,並且R的所有非主屬性都完全依賴於R的每一個候選關鍵屬性,稱R滿足第二範式,簡記為2NF。
第三範式:如果關係模式R滿足第二範式,X是R的任意屬性集,如果X非傳遞依賴於R的任意一個候選關鍵字,稱R滿足第三範式,簡記為3NF。
什麼,定義太長了,還好下麵有一個精簡的版本:
第一範式:表中不能有表,列中不能有列。
第二範式:滿足第一範式的基礎上,消除非主屬性對主屬性的部分依賴。
第三範式:滿足第二範式的基礎上,消除非主屬性對任一主屬性的傳遞依賴。
以下將嘗試對上面的釋義做一個通俗的解釋:
第一範式:表中不能有表,列中不能有列。這是對關係數據表的基本要求,同時相信也沒有人能夠在物理上突破限制,真的在表裡建出另一張子表。然而,邏輯上的“列中不能有列”卻常常被人忽略。例如,記錄用戶信息的用戶表中有一個欄位realname,記錄用戶姓名,這在中國倒很常見,但若是放眼全球,很多國家以firstname,lastname來標記姓名,仍然堅持以一個欄位來記錄姓名便會常常出現問題。因此,並不是所有關係表都能輕鬆達到嚴格的第一範式哦!
第二範式:舉個反例,設計一張學分表,包含欄位course_id(課程),stu_no(學號),score(學分),stu_name(姓名)。相信很多人看到這樣的表結構很快就能感受到一股奇怪的力量,沒錯,就是stu_name亂入了,這張表的主屬性是course_id和stu_no,score完全依賴於主屬性,而stu_name卻只依賴於stu_no不依賴於course_id,這便是部分依賴,因此,將stu_name移出表結構的過程就是消除非主屬性對於主屬性部分依賴的過程。
第三範式:仍然以例為證,設計一張訂單表,order_id(訂單號),total_fee(總價),customer_id(顧客id),customer_name(顧客姓名)。其中主屬性是order_id,其他屬性全部依賴於order_id,因此可以認為當前表結構滿足第二範式,然而,customer_id依賴於order_id,而customer_name又依賴於customer_id,這便導致了一條傳遞依賴,不滿足第三範式,因此將customer_name移出表結構的過程就是消除非主屬性對主屬性的傳遞依賴的過程。
Tips:本質上,資料庫範式的演變過程就是去除冗餘數據的過程,在實踐中,瞭解三大範式對於資料庫的設計將會大有裨益,但切記不能鑽牛角尖,因為業務場景的複雜度不在資料庫範式討論的範圍之內,如果一味強求資料庫的設計規範,很容易增加資料庫的設計和程式編碼的複雜度,因此,適當合理的數據冗餘也是可以接受的哦!遺憾的是,“適當合理的數據冗餘”並沒有量化的概念呢!