摘要:數據庫規范化設計與反規范化設計是一對互相矛盾的設計思想。本文以數據規范化理論為出發點,從合理建立關系模型和提高操作性能角度,分析規范化和反規范化的優勢和不足,并提出了幾種合理有效的策略來平衡二者之間的矛盾關系。
關鍵字:數據庫設計;規范化;反規范化;提高性能;策略
一、 數據的規范化
在設計數據庫時,最重要的一點就是確保數據正確地分布到數據庫的表中。而使用正確規范的數據結構,既方便對數據庫的存取操作,也能相應地簡化應用系統的部分內容,比如:查詢和決策報表等。
規范化理論是圍繞范式建立的,是將一個低一級范式的關系模式轉化為若干個高一級范式的關系模式的集合的過程,是數據庫設計的規范。要想設計出良好規范的數據庫,我們需要按照數據庫規范化理論來設計,滿足這些規范的數據庫結構是簡潔清晰的,同時不會發生增刪改查等方面的操作異常。
范式是對關系規范化的約束要求,如果一個關系滿足某個特定的約束值,則稱它屬于某種特定的范式。規范化理論將關系應該滿足的規范要求分成幾級,主要包括第一范式(1NF)、第二范式(2 NF)、第三范式(3NF)、鮑依斯-科得范式(BC NF)、第四范式(4 NF)和第五范式(5 NF)等。在軟件工程中第三范式和鮑依斯-科得范式應用最為廣泛,推薦采用第三范式作為標準。
二、 數據的反規范化
在數據庫系統應用中,并非采用規范化設計的程度越高越好,而是和實際系統應用的環境和要求密切相關的。對于經常需要查詢統計的數據庫應用系統,這種設計導致的后果是致命的。采用規范化設計的程度越高,對數據進行組織和拆分的程度就越深,進而產生的數據關系就越多;關系越多,連接操作相應的更為頻繁,而連接是數據庫操作最耗費時間的,頻繁地連接直接會影響系統查詢速度,特別是對于有海量數據、且需要經常使用查詢功能的數據庫應用系統,這種表現就越明顯。例如,在ERP系統的銷售管理子系統中,銷售合同的總金額是根據合同明細表中(T_OrderDetail)的所有該合同子項的單價和數量進行計算得出的,Select OrderId,sum(Price*Quantity) From T_OrderDetail Group by OrderId。
如果在合同主要信息表(T_Order)中存在合同總金額(OrderTotal)列就違反數據庫設計規范;如果合同主要信息表中不存在該列,那么若想得到合同號、合同名稱和合同總金額,則需要連接操作,Select a.OrderNo,a.OrderName,sum(b.Price*b.Quantity) From T_Order a, T_OrderDetail b
Where a.OrderId=b.OrderId Group by a.OrderNo,a.OrderName。
因此,為了改進數據庫應用系統的性能,通常需要在數據表規范化的基礎上,通過在關系模式中增加擴展列等方式來達到系統要求,系統相應地需要在數據表上創建觸發器或增加業務邏輯處理來維護擴展列的內容,這就是反規范化。
反規范化具有以下優點:有效降低連接操作的要求,降低數據外鍵和索引的數量,大大提高數據查詢速度和效率,特別是對于性能要求比較高的系統,能有效地改善系統應用的性能;還可在某種程度上減少數據表的數量。因此,在運用數據庫反規范時,需要考慮項目的實際情況、數據存儲性能、查詢性能等方面,并在此基礎上權衡利弊,綜合考慮,如果能夠通過索引、存儲過程等方法來解決的性能問題,并不一定非得使用反規范化。
通常,我們在運用反規范化技術前,需要充分考慮數據存儲性能要求、查詢頻率和性能、常用的數據表的物理存儲、數據量大小和是否有無復雜計算等方面;在此基礎上,判斷采用何種方法解決系統性能問題。目前常用的反規范方法有合理增加冗余列、派生列和合并表、分割表和增加重復表等幾種,在這里我只簡單介紹增加冗余列、派生列和合并表、分割表四種方法。
1. 增加冗余列
該方法指的是:把需要經常使用查詢操作的相關數據表的查詢數據列進行集中,并在主要的查詢數據表中增加這些冗余數據列。例如,在ERP系統的采購管理子系統中,如果經常查詢一種原材料的供應商名稱,則需要在原材料表(Stock)和供應商表(Vendor)作連接查詢:
Select a.StockCode,a.StockName,b.VenName From Stock a,Vendor b where a.VenCode=b.VenCode
針對這種情況,我們在原材料表中增加一列供應商名稱,就不需要進行連接操作了。
這種方法通常用來在查詢時有效降低數據表之間的連接操作,提高查詢速度,特別適用于日常關鍵業務數據的查詢操作,經過實際檢驗,該方法可以將查詢速度提高40%。但是,這種方法相應增加了存儲空間,并且增加了數據表的維護工作量,一般通過觸發器或應用事務邏輯來實現數據維護工作。
2. 增加派生列
派生列是指:該列的數據來自于其他數據表,并且由這些數據計算后生成。例如,前面所講的查詢合同總金額時,合同主要信息表中的合同總金額就是派生列。
增加派生列可以降低查詢時的連接操作,有效避免查詢時使用聚集函數,經過實際檢驗,該方法可以將查詢速度提高至少20%以上;該方法也需要增加存儲空間,增加數據表的維護工作,一般也是通過觸發器或應用事務邏輯來實現。
3. 合并表
該方法指的是:查詢的數據是由兩到三個數據列相對較少的數據表連接出來的結果,可以將這些數據表合并成一個數據表,進而達到降低連接操作、提高查詢性能的效果。例如,在學生管理系統中,用戶需要經常同時看到課程編號、課程名稱、任課教師編號、任課教師姓名,因此我們可以把課程表中的課程編號、課程名稱與教師表中的任課教師編號、任課教師姓名組成一個新的數據表。
這種方法雖然提高了系統性能,但是既增加了存儲空間(需要增加主鍵列),又使數據的獨立性弱化。因此,建議盡量少用,除非有特殊的需要。
4. 分割表
有些數據表隨著時間的推移,數據量越來越大,特別是達到上百萬行級甚至上千萬行級的時候,即使是使用良好的索引也不能從根本上解決問題。在這些海量數據中,數據的使用情況也不一樣:有些數據行常用,有些很少使用;有些數據列常用,有些很少使用。遇到這種情況,一般采用分割表的方法來解決。
分割表按照分割方式分為:水平分割和垂重分割。
(1)水平分割。該方法是指:在一個數據表中,根據一個或多個數據列的值,把這些數據行拆分后放到幾個獨立數據表中,這些數據表的結構完全相同。
該方法會給系統應用帶來復雜度,需要在查詢時使用多個數據表名,查詢所有數據時需要使用union連接操作;同時系統在查詢時也會增加讀索引層的磁盤次數。
該方法適用于以下幾種情況:
數據表中的數據有非常大的獨立性,有些數據常用,有些不常用。比如,數據表中記錄了不同地區或不同時期的業務數據。
數據表中的數據非常龐大,影響查詢速度。通過分割可以降低查詢時要讀的數據和索引,提高查詢速度。
數據表中的數據需要存放在不同的介質上。
(2)垂直分割。該方法是指:在一個數據表中,根據數據列的性質,把主鍵和一些列放到一個數據表中,把主鍵和另外的列放到一個數據表中。比如:根據列是否經常使用,把主鍵和常用列放到一個數據表中,把主鍵和另外不常用的列放到另外一個數據表中。
該方法可以使數據行減小,一個數據頁上可以存放更多的數據行,同時在查詢時能夠有效減少I/O次數。但是隨之帶來的是,系統需要額外管理維護冗余列,查詢時需要用join操作。
5. 反規范化適用的情況
(1)大量頻繁的查詢過程所涉及的表都需要進行連接;(2)主要的應用程序在執行時要將表連接起來進行查詢;(3)對數據的計算需要臨時表或進行復雜的查詢。
6. 小結
反規范化帶來的主要問題是增加了數據冗余度,影響數據庫的完整性,降低了數據的更新速度,增加了存儲表所占用的物理空間等。以上問題可通過建立觸發器、應用事務邏輯、運行批處理等方法來解決。其中:
(1)使用觸發器,可以對數據的任何修改操作立即觸發對冗余列或派生列的相應修改;觸發器是實時的,相應的處理邏輯只在一個地方出現,易于維護。
(2)應用事務邏輯也可以實現數據的完整性,它要求必須在同一事務中對所有涉及的表進行增、刪、改操作。用這種方法實現數據的完整性風險較大,因為同一個事務邏輯需要在所有的應用中使用和維護,容易遺漏,也不易于以后的維護工作。
(3)運行批處理命令是指對冗余列或派生列的修改在累積到一定時間后,運行批處理命令或存儲過程對冗余或派生列進行修改,這只能在對實時性要求不高的情況下使用。
反規范化的主要優點是減少了查詢操作所需的連接,減少了外部鍵和索引的數量,可以預先進行統計計算,有效提高了查詢時的響應速度。
三、 結束語
在數據庫管理應用系統設計中,運用規范化設計能夠有效消除數據冗余,理順數據隸屬關系,保持數據庫的完整性,提高數據庫的穩定性和擴展性,同時也帶來了查詢時增加連接操作、系統性能不高的問題,而使用反規范化設計帶來的效果卻恰恰相反。
在某種意義上,數據庫的規范化與反規范化設計并不是對立的矛盾關系,關鍵在于我們如何解決數據庫管理應用系統的實際需求,在平衡二者在設計上帶來的便利和不足的前提下,權衡利弊,采用二者結合的方式也許是目前解決用戶實際業務需求的最好的辦法。
參考文獻:
[1]周渝斌.基于ORACLE8i的大型數據庫技術講座之一數據庫優 化篇[J].電腦編程技巧與維護,2002(4).
[2]Kevin Loney.Oracle8i 數據庫管理員手冊[M].北京:機械工業
出版社,2000.
(滄州職業技術學院信息工程系)