資料庫設計中的反規範技術探討(轉)

PigBaby2007發表於2007-08-08
原標題:淺談資料庫設計中的反規範 [@more@]


1. 摘要

 本文從提高資料庫效能的角度,介紹了資料庫設計中幾種常用的反規範方法,並對廡┓椒ǖ撓湃鋇鬩約笆褂檬鋇淖⒁饈孿鈄雋私銜?釗氳穆凼觥!?
關鍵詞: 資料庫設計  反規範  提高效能


2. 資料庫設計簡述
資料庫設計是把現實世界的商業模型與需求轉換成資料庫的模型的過程,它是建立資料庫應用系統的核心問題。設計的關鍵是如何使設計的資料庫能合理地儲存使用者的資料,方便使用者進行資料處理。 
 資料庫設計完全是人的問題,而不是資料庫管理系統的問題。系統不管設計是好是壞,照樣執行。資料庫設計應當由資料庫管理員和系統分析員一起和使用者一道工作,瞭解各個使用者的要求,共同為整個資料庫做出恰當的、完整的設計。  
資料庫及其應用的效能和調優都是建立在良好的資料庫設計的基礎上,資料庫的資料是一切操作的基礎,如果資料庫設計不好,則其它一切調優方法提高資料庫效能的效果都是有限的。  
資料的規範化

2.1. 正規化概述
     規範化理論是研究如何將一個不好的關係模式轉化為好的關係模式的理論,規範化理論是圍繞正規化而建立的。規範化理論認為,一個關聯式資料庫中所有的關係,都應滿足一定的規範(約束條件)。規範化理論把關係應滿足的規範要求分為幾級,滿足最低要求的一級叫做第一正規化(1NF),在第一正規化的基礎上提出了第二正規化(2NF),在第二正規化的基礎上又提出了第三正規化(3NF),以後又提出了BCNF正規化,4NF,5NF。正規化的等級越高,應滿足的約束集條件也越嚴格。規範的每一級別都依賴於它的前一級別,例如若一個關係模式滿足2NF,則一定滿足1NF。下面我們只介紹1NF,2NF,3NF正規化。  

2.2. 1NF
1NF是關係模型的最低要求,它的規則是:   
每一列必須是原子的,不能分成多個子列。
每一行和列的位置只能有一個值。
不能具有多值列。
例:如果要求一個學生一行,一個學生可選多門課,則下面的“學生”表就不滿足1NF:
student(s-no,s-name,class-no)
其中:s-no為學號,s-name為學生姓名,class-no為課程號。因為一個學生可選多門課,所以列class-no有多個值,所以空不符合1NF。
  規範化就是把它分成如下兩個表:“學生”表和“選課”表,則這兩個表就都滿足1NF了。
student(s-no,s-name)
stu-class(s-no,class-no)   

2.3. 2NF
  對於滿足2NF的表,除滿足1NF外,非主碼的列必須依賴於所有的主碼,而不是組合主碼的一部分。如果滿足1NF的表的主碼只有一列,則它自動滿足2NF。  例:下面的“選課”表,不符合2NF。
stu-class(s-no,class-no,class-name)
其中:class-name為課程名稱。因為詞表的主碼是:(s-no,class-no),非主碼列class-name依賴於組合主碼的一部分class-no,所以它不符合2NF。
對該表規範化也是把它分解成兩個表:“選課”表和“課程”表,則它們就都滿足2NF了。
stu-class(s-no,class-no)
class(class-no,class-name)   

2.4. 3NF
  3NF的規則是除滿足2NF外,任一非主碼列不能依賴於其它非主碼列。   例:下面的“課程”表,不符合3NF。
class(class-no,class-name,teacher-no,teacher-name)
其中:teacher-no為任課教師號,teacher-name為任課教師姓名。因為非主碼列teacher-name依賴於另一非主碼列teacher-no,所以它不符合3NF。  其解決辦法也是把它分解成兩個表:“課程”表和“教師”表,則它們就都滿足3NF了。   
class(class-no,class-name,teacher-no)
teacher(teacher-no,teacher-name)  

2.5. 小結
  當一個表是規範的,則其非主碼列依賴於主碼列。從關係模型的角度來看,表滿足3NF最符合標準,這樣的設計容易維護。一個完全規範化的設計並不總能生成最優的效能,因此通常是先按照3NF設計,如果有效能問題,再透過反規範來解決。  
資料庫中的資料規範化的優點是減少了資料冗餘,節約了儲存空間,相應邏輯和物理的I/O次數減少,同時加快了增、刪、改的速度,但是對完全規範的資料庫查詢,通常需要更多的連線操作,從而影響查詢的速度。因此,有時為了提高某些查詢或應用的效能而破壞規範規則,即反規範。

3. 資料的反規範

3.1. 反規範的好處
是否規範化的程度越高越好?這要根據需要來決定,因為“分離”越深,產生的關係越多,關係過多,連線操作越頻繁,而連線操作是最費時間的,特別對以查詢為主的資料庫應用來說,頻繁的連線會影響查詢速度。所以,關係有時故意保留成非規範化的,或者規範化以後又反規範了,這樣做通常是為了改進效能。例如帳戶系統中的“帳戶”表B-TB01,它的列busi-balance(企業帳戶的總餘額)就違反規範,其中的值可以透過下面的查詢獲得: 
select busi-code,sum(acc-balance)  
from B-TB06   
group by busi-code
  如果B-TB01中沒有該列,若想獲得busi-name(企業名稱)和企業帳戶的總餘額,則需要做連線操作:  
select busi-name,sum(acc-balance)   
from B-TB01,B-TB06   
where B-TB01.busi-code=B-TB06.busi-code   
group by busi-code
如果經常做這種查詢,則就有必要在B-TB01中加入列busi-balance,相應的代價則是必須在表B-TB06上建立增、刪、改的觸發器來維護B-TB01表上busi-balance列的值。類似的情況在決策支援系統中經常發生。  
反規範的好處是降低連線操作的需求、降低外碼和索引的數目,還可能減少表的數目,相應帶來的問題是可能出現資料的完整性問題。加快查詢速度,但會降低修改速度。因此決定做反規範時,一定要權衡利弊,仔細分析應用的資料存取需求和實際的效能特點,好的索引和其它方法經常能夠解決效能問題,而不必採用反規範這種方法。  


3.2. 常用的反規範技術
在進行反規範操作之前,要充分考慮資料的存取需求、常用表的大小、一些特殊的計算(例如合計)、資料的物理儲存位置等。常用的反規範技術有增加冗餘列、增加派生列、重新組表和分割表。 

3.2.1. 增加冗餘列

增加冗餘列是指在多個表中具有相同的列,它常用來在查詢時避免連線操作。例如前面例子中,如果經常檢索一門課的任課教師姓名,則需要做class和teacher表的連線查詢:
  select class-name,teacher-name   
from class,teacher   
where class.teacher-no=teacher.teacher-no   
這樣的話就可以在class表中增加一列teacher-name就不需要連線操作了。
增加冗餘列可以在查詢時避免連線操作,但它需要更多的磁碟空間,同時增加表維護的工作量。

3.2.2. 增加派生列
增加派生列指增加的列來自其它表中的資料,由它們計算生成。它的作用是在查詢時減少連線操作,避免使用集函式。例如前面所講的賬戶系統中的表B-TB01的列busi-balance就是派生列。派生列也具有與冗餘列同樣的缺點。

3.2.3. 重新組表
重新組表指如果許多使用者需要檢視兩個表連線出來的結果資料,則把這兩個表重新組成一個表來減少連線而提高效能。例如,使用者經常需要同時檢視課程號,課程名稱,任課教師號,任課教師姓名,則可把表class(class-no,class-name,teacher-no)和表teacher(teacher-no,teacher-name)合併成一個表class(class-no,class-name,teacher-no,teacher-name)。這樣可提高效能,但需要更多的磁碟空間,同時也損失了資料在概念上的獨立性。  

3.2.4. 分割表
有時對錶做分割可以提高效能。表分割有兩種方式: 
1水平分割:根據一列或多列資料的值把資料行放到兩個獨立的表中。   水平分割通常在下面的情況下使用:A 表很大,分割後可以降低在查詢時需要讀的資料和索引的頁數,同時也降低了索引的層數,提高查詢速度。B 表中的資料本來就有獨立性,例如表中分別記錄各個地區的資料或不同時期的資料,特別是有些資料常用,而另外一些資料不常用。C 需要把資料存放到多個介質上。   例如法規表law就可以分成兩個表active-law和inactive-law。activea-authors表中的內容是正生效的法規,是經常使用的,而inactive-law表則使已經作廢的法規,不常被查詢。水平分割會給應用增加複雜度,它通常在查詢時需要多個表名,查詢所有資料需要union操作。在許多資料庫應用中,這種複雜性會超過它帶來的優點,因為只要索引關鍵字不大,則在索引用於查詢時,表中增加兩到三倍資料量,查詢時也就增加讀一個索引層的磁碟次數。
  2垂直分割:把主碼和一些列放到一個表,然後把主碼和另外的列放到另一個表中。如果一個表中某些列常用,而另外一些列不常用,則可以採用垂直分割,另外垂直分割可以使得資料行變小,一個資料頁就能存放更多的資料,在查詢時就會減少I/O次數。其缺點是需要管理冗餘列,查詢所有資料需要join操作。  

4. 反規範技術需要維護資料的完整性
  無論使用何種反規範技術,都需要一定的管理來維護資料的完整性,常用的方法是批處理維護、應用邏輯和觸發器。批處理維護是指對複製列或派生列的修改積累一定的時間後,執行一批處理作業或儲存過程對複製或派生列進行修改,這隻能在對實時性要求不高的情況下使用。資料的完整性也可由應用邏輯來實現,這就要求必須在同一事務中對所有涉及的表進行增、刪、改操作。用應用邏輯來實現資料的完整性風險較大,因為同一邏輯必須在所有的應用中使用和維護,容易遺漏,特別是在需求變化時,不易於維護。另一種方式就是使用觸發器,對資料的任何修改立即觸發對複製列或派生列的相應修改。觸發器是實時的,而且相應的處理邏輯只在一個地方出現,易於維護。一般來說,是解決這類問題的最好的辦法。  

5. 結束語
    資料庫的反規範設計可以提高查詢效能。常用的反規範技術有增加冗餘列、增加派生列、重新組表和分割表。但反規範技術需要維護資料的完整性。因此在做反規範時,一定要權衡利弊,仔細分析應用的資料存取需求和實際的效能特點。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10144097/viewspace-934451/,如需轉載,請註明出處,否則將追究法律責任。

相關文章