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


       當我們拿到一個新的需求,我們把需求從頭到尾分析清楚后,就開始一步一步開發了,具體流程:

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

       在這里我們只對設計數據庫的這一塊的范式進行討論。提到范式,大家都知道第一范式,第二范式,第三范式。可是我們明白這些范式的深層含意嗎?這些范式什么時候用,用它們有什么好處呢?下面就和大家一起探討這些問題

     所謂范式 :英文名稱是 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得到的緩存數據是一致的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM