自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么我不喜歡數(shù)據(jù)庫三范式?

數(shù)據(jù)庫 MySQL
這里,不想花太多的篇幅去討論理論性的東西,這些信息一抓一大把。我們就通過一些簡單的例子來體會一下。

 [[335318]]

插曲

最近,一個遠(yuǎn)房親戚的小表弟準(zhǔn)備選修專業(yè)

找到我問:

    "哥,現(xiàn)在學(xué)數(shù)據(jù)庫有沒有前途阿?"

    "當(dāng)然有啊,前途大大的呢"

    "那我現(xiàn)在開始學(xué)數(shù)據(jù)庫,需要先從什么開始呢?"

    "學(xué)課程的話,先了解下數(shù)據(jù)庫三范式,SQL這些吧"

    "SQL我大概知道,數(shù)據(jù)庫三范式是什么?"

    "阿...三范式就是表的主鍵...唯一性那些東西吧,...嗯,應(yīng)該就是那些"

    "什么是主鍵?"

    "額.....表弟你不要再問了啦,好好去百度一下行不。"

    "噢...."

掛完電話,我舒了口氣,由于差點暴露自己已經(jīng)不記得三范式了這個不爭的事實,我悄悄打開了谷歌....

數(shù)據(jù)庫的這個三范式的概念,相信大多數(shù)人都不會陌生,從懵懵懂懂的大學(xué)時代就已經(jīng)普及到教材了(沒記錯的話應(yīng)該在數(shù)據(jù)庫系統(tǒng)概論這本教材里)。還記得那會剛開始找實習(xí)的時候,由于自己本事太小,連簡歷都不知道怎么寫好,尤其是擅長技術(shù)的部分更是一片空白。于是乎會找來隔壁幾個學(xué)霸的簡歷來做參考,那會兒大家的簡歷上都會赫赫寫著:

熟練掌握數(shù)據(jù)庫三范式,精通數(shù)據(jù)庫系統(tǒng)開發(fā)語言

又或者是:

熟悉ER圖制作工具,能實現(xiàn)滿足三范式的數(shù)據(jù)庫設(shè)計

一開始覺得數(shù)據(jù)庫三范式確實是個好東西,以至于面試的時候技術(shù)官沒有提問到三范式的細(xì)節(jié),自己感到了驚訝和茫然。隨著工作經(jīng)驗逐漸見長,數(shù)據(jù)庫范式理論在腦海里的強(qiáng)印象漸漸消除。我在想,要么是記憶的衰退,要么就是有些原則已經(jīng)形成了本能的經(jīng)驗了。

那么,什么是數(shù)據(jù)庫的范式?

三范式的定義

這里,不想花太多的篇幅去討論理論性的東西,這些信息一抓一大把。我們就通過一些簡單的例子來體會一下。

1. 第一范式

假設(shè)有一張用戶信息表,上面除了用戶編號、姓名之外,還會記錄地址信息:

編號 姓名 性別 所在地
0001 張三 廣東省,深圳市
0002 李四 海南省,??谑?/span>

在這里面,地址信息一欄就是不符合第一范式(1NF)的:

第一范式(1NF):數(shù)據(jù)庫表的每一列都是不可分割的原子項

因此,應(yīng)該拆分為:

編號 姓名 性別 所在省 地市
0001 張三 廣東省 深圳市
0002 李四 海南省 ??谑?/span>

2. 第二范式

以一個訂單表為例,通常在淘寶上下單時會產(chǎn)生包含多個商品的訂單,如下:

訂單號 商品號 商品名稱 價格
o1 g1 洗衣液 23
o1 g2 吹風(fēng)機(jī) 125
o1 g3 蠶豆 5
o2 g9 被子 302
o2 g8 枕頭 69

這里同樣違反了第二范式的定義:

第二范式(2NF):每個表必須有且僅有一個數(shù)據(jù)元素為主鍵(Primary key),其他屬性需完全依賴于主鍵

第二范式需建立在滿足第一范式的基礎(chǔ)之上

第二范式首先要求的是存在一個唯一的主鍵,在上面的表中,就必須將 訂單號、商品號 作為一個聯(lián)合的主鍵才能滿足要求。那么對于第二點要求呢?其他屬性是否依賴于這個主鍵?在訂單的場景中,我們可以認(rèn)為這算是合理的,因為商品的價格甚至名稱都可能會發(fā)生變化,而在每個訂單中所看到的這些信息都應(yīng)該是不變的,

誰也不希望看到自己已經(jīng)支付的訂單中的商品信息突然大降價.. 當(dāng)然更重要的還是保持訂單總價與商品單價記錄的一致性。因此這里的記錄可以認(rèn)為是商品信息在創(chuàng)建訂單時的一個快照。

但是,對于下面的這一場景可能就不合適了:

訂單號 商品號 商品名稱 價格 商品類別
o1 g1 洗衣液 23 家居
o1 g2 吹風(fēng)機(jī) 125 電器
o1 g3 蠶豆 5 食品
o2 g9 被子 302 家居
o2 g8 枕頭 69 家居

商品所屬的類別一般是固定的,也就是商品的類別屬性僅僅與商品編號相關(guān),即僅僅是依賴于主鍵的一部分。這就違反了第二范式中"其他屬性必須完全依賴于主鍵"的規(guī)則,因此需要將該屬性分離到商品信息表中。

3. 第三范式

讓我們回到一開始的用戶表,如果在用戶信息表中,同時補(bǔ)充一些城市的信息:

編號 姓名 性別 城市 城市特色 城市人口
0001 張三 深圳市 科技、創(chuàng)新 1300W
0002 李四 ??谑?/span> 旅游、觀光 230W

這樣便違反了第三范式的定義:

第三范式(3NF):數(shù)據(jù)表中的每一列都和主鍵直接相關(guān),而不能間接相關(guān)

同樣,第三范式也需要建立在第二范式的基礎(chǔ)之上

很明顯,這里的城市人口、特色等屬性都僅僅依賴于用戶所在的城市,而不是用戶,只能算間接的關(guān)系。因此最好的做法是將城市相關(guān)的屬性分離到一個城市信息表中。

為什么需要范式

數(shù)據(jù)庫范式為數(shù)據(jù)庫的設(shè)計、開發(fā)提供了一個可參考的典范,在許多教學(xué)材料中也是作為關(guān)鍵的課程內(nèi)容。那么范式的提出是為了解決什么問題?

  •  第一范式,要求將列盡可能最小的分割,希望消除某個列存儲多個值的冗余的行為。比如用戶表中的地址信息,拆分為省、市這種明確的字段,可以按獨立的字段檢索、查詢。
  •  第二范式,要求唯一的主鍵,且不存在對主鍵的部分依賴,希望消除表中存在冗余(多余)的列。比如訂單表中的商品分類、詳情信息,只需要由商品信息表存儲一份即可。
  •  第三范式,要求沒有間接依賴于主鍵的列,即仍然是希望消除表中冗余的列。比如用戶表中不需要存儲額外的 其所在城市的人口、城市特點等信息。

很明顯,這些范式大都是為了消除冗余而提出的,這有利于數(shù)據(jù)的一致性,當(dāng)然也可以盡可能的減少存儲成本。

PS:你懂得三范式,可以幫老板省錢,難怪簡歷上要寫上..

[[335319]]

除了本文中提到的三范式之外,實質(zhì)上還有BCNF范式、第四、第五范式。

借助三范式的理念,你可以設(shè)計出很精煉的數(shù)據(jù)庫表結(jié)構(gòu)。然而現(xiàn)有的項目應(yīng)用并不會完全遵循范式的理念,原因比如:

  •  性能原因,沒有任何冗余的表設(shè)計會產(chǎn)生更多的查詢行為,這意味著會產(chǎn)生更多次的數(shù)據(jù)庫IO操作。在一些實時交互的系統(tǒng)中,可能會慢得讓人難以忍受。當(dāng)然,你可以使用數(shù)據(jù)庫的 連接(join) 操作,而事實上數(shù)據(jù)庫提供 join 也就是為了來緩解這種問題。但一旦用到了分庫分表方案,這個問題就會非常的棘手。
  •  成本結(jié)構(gòu)的變化,數(shù)據(jù)庫范式是在20世紀(jì)提出的,當(dāng)時的磁盤存儲成本還很高。隨著科技發(fā)展,數(shù)據(jù)存儲的成本已經(jīng)大幅度縮減,對于采用范式設(shè)計(規(guī)避冗余)帶來的成本縮減收益已經(jīng)不那么明顯。

反范式設(shè)計

既然范式是為了消除冗余,那么反范式就是通過增加冗余、聚合的手段來提升性能。比如,為了提升查詢的性能,在CMS的文章表中同時冗余作者的信息。冗余的做法會犧牲一定的數(shù)據(jù)一致性,或是帶來數(shù)據(jù)同步的麻煩,但通常也是需要業(yè)務(wù)上進(jìn)行權(quán)衡取舍。

當(dāng)然,除了冗余(存儲多份拷貝) 之外,還有另外的理念,即數(shù)據(jù)的聚合,或者叫嵌套。這種做法相當(dāng)于是將多個字段(列)合并存儲到數(shù)據(jù)庫表的一個列中。

比如一條訂單數(shù)據(jù)就可以同時包含許多信息:   

  1.  
  2.    "oid": "0001",  
  3.    "price": {  
  4.    "total": 380,  
  5.    "benefit": 40  
  6.     },  
  7.    "goods": [{  
  8.    "gid": "SN001",  
  9.    "name": "藍(lán)月亮洗衣液",  
  10.    "price": 41,  
  11.    "amount": 2  
  12.      },  
  13.      {  
  14.    "gid": "SN003",  
  15.    "name": "電動剃須刀",  
  16.    "price": 99,  
  17.    "amount": 1  
  18.      }  
  19.     ],  
  20.    "address": {  
  21.    "contact": "張三",  
  22.    "phone": "150899000"  
  23.       ...  
  24.     }  
  25.    ...  
  26.    } 

這種靈活的結(jié)構(gòu)幾乎是 NoSQL 的專利,比如 MongoDB 文檔數(shù)據(jù)庫就可以直接以內(nèi)嵌數(shù)組、對象的形式來實現(xiàn)聚合式存儲,這無疑帶來了極大的靈活性。而 MySQL 在5.2.7版本開始支持JSON結(jié)構(gòu)化列,也進(jìn)入了聚合式存儲的隊伍,與其對標(biāo)的PostGreSQL 則是9.4版本就已經(jīng)支持。

反范式的做法在互聯(lián)網(wǎng)項目、開源產(chǎn)品中也比較常見,比如Discuz 的數(shù)據(jù)表設(shè)計中就存在許多的冗余列、聚合字段。一方面,除了能獲得性能的提升之外,數(shù)據(jù)壓縮、高度靈活擴(kuò)展(非結(jié)構(gòu)化) 也是反范式設(shè)計能獲得青睞的理由。

當(dāng)然,這里并非一律反對數(shù)據(jù)庫范式,理解范式仍然是做好數(shù)據(jù)庫設(shè)計的一門基礎(chǔ),比如選擇合適的主鍵、清晰的劃分每一列屬性等等。在項目中仍然需要根據(jù)自身的業(yè)務(wù)特點在范式和反范式中找到平衡點(通常是兩者的結(jié)合)。類似于架構(gòu)設(shè)計中空間換時間的一些做法,這其中涉及到的各種取舍都是需要經(jīng)過權(quán)衡的。 

 

責(zé)任編輯:龐桂玉 來源: ITPUB
相關(guān)推薦

2018-01-09 18:46:44

數(shù)據(jù)庫架構(gòu)讀寫分離

2018-01-15 05:54:45

數(shù)據(jù)庫讀寫分離互聯(lián)網(wǎng)

2015-10-26 09:58:53

程序員主流

2012-04-04 22:07:12

Android

2017-03-03 15:23:46

數(shù)據(jù)庫設(shè)計范式

2021-01-30 10:51:07

Python編程語言開發(fā)

2019-10-23 15:53:16

JavaScript可選鏈對象

2009-06-04 17:33:08

EJB 3.1EJB 3.0

2022-06-04 15:28:42

微服務(wù)架構(gòu)編程語言

2019-08-28 10:53:35

JavaScriptOptional Ch代碼

2010-08-23 09:46:17

開發(fā)者

2022-12-27 08:38:45

關(guān)系型數(shù)據(jù)庫設(shè)計

2023-09-14 08:00:00

基于主干的開發(fā)分支模型

2025-01-15 09:06:58

CSSRegEx前端

2011-04-21 13:53:52

2010-06-11 13:48:38

Ubuntu 10.0

2020-11-13 09:22:32

Docker數(shù)據(jù)庫容器

2017-11-30 15:25:04

EclipseGo項目

2017-09-11 19:58:06

PostgreSQLMySQL數(shù)據(jù)庫

2020-03-27 16:05:49

數(shù)據(jù)庫數(shù)據(jù)MySQL
點贊
收藏

51CTO技術(shù)棧公眾號