數據庫設計之三範式與反範式

       當咱們拿到一個新的需求,咱們把需求從頭至尾分析清楚後,就開始一步一步開發了,具體流程:數據庫

                畫流程圖—>用例圖—->設計數據庫—->進入開發階段—->編碼—->測試—–>項目上線,至此一個項 目就算完成。設計模式

       在這裏咱們只對設計數據庫的這一塊的範式進行討論。提到範式,你們都知道第一範式,第二範式,第三範式。但是咱們明白這些範式的深層含意嗎?這些範式何時用,用它們有什麼好處呢?下面就和你們一塊兒探討這些問題緩存

     所謂範式 :英文名稱是 Normal Form,它是英國人 E.F.Codd(關係數據庫的老祖宗)在上個世紀70年代提出關係數據庫模型後總結出來的,範式是關係數據庫理論的基礎,也是咱們在設計數據庫結構過程 中所要遵循的規則和指導方法。數據庫的設計範式是數據庫設計所須要知足的規範。只有理解數據庫的設計範式,才能設計出高效率、優雅的數據庫,不然可能會設 計出錯誤的數據庫.目前有跡可尋的共有8種範式,依次是:1NF,2NF,3NF,BCNF,4NF,5NF,DKNF,6NF。知足最低要求的叫第一範 式,簡稱1NF。在第一範式基礎上進一步知足一些要求的爲第二範式,簡稱2NF。其他依此類推。一般所用到的只是前三個範式,即:第一範式(1NF),第 二範式(2NF),第三範式(3NF)。下面就簡單介紹下這三個範式。數據庫設計

   ◆ 第一範式(1NF)無重複的列.表中的每一列都是不可分割的基本數據項.不知足1NF的數據庫不是關係數據庫.
考慮這樣一個表:【聯繫人】(姓名,性別,電話)
若是在實際場景中,一個聯繫人有家庭電話和公司電話,那麼這種表結構設計就沒有達到 1NF。要符合 1NF 咱們只需把列(電話)拆分,即:【聯繫人】(姓名,性別,家庭電話,公司電話)。1NF 很好辨別,可是 2NF 和 3NF 就容易搞混淆。分佈式

   ◆ 第二範式(2NF)屬性徹底依賴於主鍵。首先要知足它是1NF,另外還須要包含兩部份內容:一是表必須有一個主鍵;二是沒有包含在主鍵中的列必須徹底依賴於主鍵,而不能只依賴於主鍵的一部分。
考慮一個訂單明細表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。
由於咱們知道在一個訂單中能夠訂購多種產品,因此單單一個 OrderID 是不足以成爲主鍵的,主鍵應該是(OrderID,ProductID)。顯而易見 Discount(折扣),Quantity(數量)徹底依賴(取決)於主鍵(OderID,ProductID),而 UnitPrice,ProductName 只依賴於 ProductID。因此 OrderDetail 表不符合 2NF。不符合 2NF 的設計容易產生冗餘數據。
能夠把【OrderDetail】表拆分爲【OrderDetail】(OrderID,ProductID,Discount,Quantity)和 【Product】(ProductID,UnitPrice,ProductName)來消除原訂單表中UnitPrice,ProductName多 次重複的狀況。性能

    ◆ 第三範式(3NF)屬性不傳遞依賴於其它非主屬性 首先是知足 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的狀況。
考慮一個訂單表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主鍵是(OrderID)。
其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity 等非主鍵列都徹底依賴於主鍵(OrderID),因此符合 2NF。不過問題是 CustomerName,CustomerAddr,CustomerCity 直接依賴的是 CustomerID(非主鍵列),而不是直接依賴於主鍵,它是經過傳遞才依賴於主鍵,因此不符合 3NF。
經過拆分【Order】爲【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)從而達到 3NF。 測試

   問題分析:優化

   1:第二範式和第三範式如何區別? 網站

        第二範式:非主鍵列是否依賴主鍵(包括一列經過某一列間接依賴主鍵),要是有依賴關係的就是第二範式;
        第三範式:非主鍵列是不是直接依賴主鍵,不能是那種經過傳遞關係的依賴的。要是符合這種就是第三範式;編碼

    2:範式的存在有什麼好處? 

        範式能夠避免數據冗餘,減小數據庫的空間,減輕維護數據完整性的麻煩。

    範式的優缺點

        範式再給咱們帶來的上面的好處時,同時也伴隨着一些很差的地方:按照範式的規範設計出來的表,等級越高的範式設計出來的表越多。如第一範式可能設計 出來的表可能只有一張表而已,再按照第二範式去設計這張表時就可能出來兩張或更多張表,若是再按第三範式或更高的範式去設計這張表會出現更多比第二範式多 的表。表的數量越多,當咱們去查詢一些數據,必然要去多表中去查詢數據,這樣查詢的時間要比在一張表中查詢中所用的時間要高不少。

也就是說咱們所用的範式越高,對數據操做的性能越低。因此咱們在利用範式設計表的時候,要根據具體的需求再去權衡是否使用更高範式去設計表。在通常的項目中,咱們用的最多也就是第三範式,第三範式也就能夠知足咱們的項目需求,性能好並且方便管理數據;

當咱們的業務所涉及的表很是多,常常會有多表發生關係,而且咱們對錶的操做要時間上要儘可能的快,這時能夠考慮咱們使用「反範式」。

      反範式   

       所謂反範式,故名思義,跟範式所要求的正好相反,在反範式的設計模式,咱們能夠容許適當的數據的冗餘,用這個冗餘去取操做數據時間的縮短也就是利用空間來換取時間,把數據冗餘在多個表中,當查詢時能夠減小或者是避免表之間的關聯;

  場景分析:

   如咱們如今要對一個 學校的課程表進行操做,如今有兩張表,一張是學生信息student(a_id,a_name,a_adress,b_id)表,一張是課程表 subject(b_id,b_subject),如今咱們須要一個這樣的信息,把選擇每一個課程的的課程名稱和學生姓名輸出來:

  SQL語句爲:select  B.b_id,B.b_subject,A_a_name from student A ,subject B;

   當上面的數據量很少時,咱們這樣去查詢沒有問題;當咱們的兩張表的數據都是在百萬級的時候,咱們去查上面的信息, 問題出現了,這個查詢動不動就是幾百毫秒,甚至更慢,這樣的查詢效率根本不能知足咱們對於網頁速度的要求(通常不能超過100毫秒),怎麼辦?固然要反範式,在課程表裏面添加冗餘字段——學生姓名,這樣咱們就能夠經過下面的查詢達到一樣的目的:

SQL語句爲:select  b_id,b_subject,a_name from subject B;

     將兩個查詢放在一塊兒查看執行計劃,就會發現,第一個查詢開銷佔了92%,而第二個才8%,也就是說,第二個查詢比起第一個查詢,效率上優化了10倍以上,成果顯著啊。

總結:

    當咱們開始着手一個項目後,範式的應用是這樣的變化的:

    第三範式數據庫的設計—–>當數據量愈來愈大,達到百萬級時,常常要對一些多表數據進行大範圍高頻率進行操做——->範式數據庫的設計———->網站的數據量再持續增加———->範式和反範式的數據庫設計

     當咱們的數據量很是大,目前除了對數據庫的設計改動外,還能夠經過對數據層進行緩存處理。如如今使用效果顯著的Memcached ,一個分佈式的緩存系統,咱們將數據庫信息以實體類的方式和圖片文件等保存在Memcached裏面,只要是可序列化的數據,通過裝箱和拆箱,均可以保存 到Memcached中並隨時能夠快速的訪問到這些對象,Memcached能夠解決大量數據的緩存並保持多臺Web Server獲得的緩存數據是一致的。

相關文章
相關標籤/搜索