數據庫設計中的反規范技術探討
2024-07-21 02:39:10
供稿:網友
1. 數據庫設計簡述
數據庫設計是把現實世界的商業模型與需求轉換成數據庫的模型的過程,它是建立數據庫應用系統的核心問題。設計的要害是如何使設計的數據庫能合理地存儲用戶的數據,方便用戶進行數據處理。
數據庫設計完全是人的問題,而不是數據庫治理系統的問題。系統不管設計是好是壞,照樣運行。數據庫設計應當由數據庫治理員和系統分析員一起和用戶一道工作,了解各個用戶的要求,共同為整個數據庫做出恰當的、完整的設計。
數據庫及其應用的性能和調優都是建立在良好的數據庫設計的基礎上,數據庫的數據是一切操作的基礎,假如數據庫設計不好,則其它一切調優方法提高數據庫性能的效果都是有限的。
數據的規范化
1.1. 范式概述
規范化理論是研究如何將一個不好的關系模式轉化為好的關系模式的理論,規范化理論是圍繞范式而建立的。規范化理論認為,一個關系數據庫中所有的關系,都應滿足一定的規范(約束條件)。規范化理論把關系應滿足的規范要求分為幾級,滿足最低要求的一級叫做第一范式(1NF),在第一范式的基礎上提出了第二范式(2NF),在第二范式的基礎上又提出了第三范式(3NF),以后又提出了BCNF范式,4NF,5NF。范式的等級越高,應滿足的約束集條件也越嚴格。規范的每一級別都依靠于它的前一級別,例如若一個關系模式滿足2NF,則一定滿足1NF。下面我們只介紹1NF,2NF,3NF范式。
1.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)
1.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)
1.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)
1.5. 小結
當一個表是規范的,則其非主碼列依靠于主碼列。從關系模型的角度來看,表滿足3NF最符合標準,這樣的設計輕易維護。一個完全規范化的設計并不總能生成最優的性能,因此通常是先按照3NF設計,假如有性能問題,再通過反規范來解決。
數據庫中的數據規范化的優點是減少了數據冗余,節約了存儲空間,相應邏輯和物理的I/O次數減少,同時加快了增、刪、改的速度,但是對完全規范的數據庫查詢,通常需要更多的連接操作,從而影響查詢的速度。因此,有時為了提高某些查詢或應用的性能而破壞規范規則,即反規范。
2. 數據的反規范
2.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列的值。
類似的情況在決策支持系統中經常發生。
反規范的好處是降低連接操作的需求、降低外碼和索引的數目,還可能減少表的數目,相應帶來的問題是可能出現數據的完整性問題。加快查詢速度,但會降低修改速度。因此決定做反規范時,一定要權衡利弊,仔細分析應用的數據存取需求和實際的性能特點,好的索引和其它方法經常能夠解決性能問題,而不必采用反規范這種方法。
2.2. 常用的反規范技術
在進行反規范操作之前,要充分考慮數據的存取需求、常用表的大小、一些非凡的計算(例如合計)、數據的物理存儲位置等。常用的反規范技術有增加冗余列、增加派生列、重新組表和分割表。
2.2.1. 增加冗余列
增加冗余列是指在多個表中具有相同的列,它常用來在查詢時避免連接操作。例如前面例子中,假如經常檢索一門課的任課教師姓名,則需要做class和teacher表的連接查詢:
select class-name,teacher-name
from class,teacher
where class.teacher-no=teacher.teacher-no
這樣的話就可以在class表中增加一列teacher-name就不需要連接操作了。
增加冗余列可以在查詢時避免連接操作,但它需要更多的磁盤空間,同時增加表維護的工作量。
2.2.2. 增加派生列
增加派生列指增加的列來自其它表中的數據,由它們計算生成。它的作用是在查詢時減少連接操作,避免使用集函數。例如前面所講的賬戶系統中的表B-TB01的列busi-balance就是派生列。派生列也具有與冗余列同樣的缺點。
2.2.3. 重新組表
重新組表指假如許多用戶需要查看兩個表連接出來的結果數據,則把這兩個表重新組成一個表來減少連接而提高性能。例如,用戶經常需要同時查看課程號,課程名稱,任課教師號,任課教師姓名,則可把表class(class-no,class-name,teacher-no)和表teacher(teacher-no,teacher-name)合并成一個表class(class-no,class-name,teacher-no,teacher-name)。這樣可提高性能,但需要更多的磁盤空間,同時也損失了數據在概念上的獨立性。
2.2.4. 分割表
有時對表做分割可以提高性能。表分割有兩種方式:
1水平分割:根據一列或多列數據的值把數據行放到兩個獨立的表中。 水平分割通常在下面的情況下使用:A 表很大,分割后可以降低在查詢時需要讀的數據和索引的頁數,同時也降低了索引的層數,提高查詢速度。B 表中的數據本來就有獨立性,例如表中分別記錄各個地區的數據或不同時期的數據,非凡是有些數據常用,而另外一些數據不常用。C 需要把數據存放到多個介質上。 例如法規表law就可以分成兩個表active-law和inactive-law。activea-authors表中的內容是正生效的法規,是經常使用的,而inactive-law表則使已經作廢的法規,不常被查詢。水平分割會給應用增加復雜度,它通常在查詢時需要多個表名,查詢所有數據需要union操作。在許多數據庫應用中,這種復雜性會超過它帶來的優點,因為只要索引要害字不大,則在索引用于查詢時,表中增加兩到三倍數據量,查詢時也就增加讀一個索引層的磁盤次數。
2垂直分割:把主碼和一些列放到一個表,然后把主碼和另外的列放到另一個表中。假如一個表中某些列常用,而另外一些列不常用,則可以采用垂直分割,另外垂直分割可以使得數據行變小,一個數據頁就能存放更多的數據,在查詢時就會減少I/O次數。其缺點是需要治理冗余列,查詢所有數據需要join操作。
3. 反規范技術需要維護數據的完整性
無論使用何種反規范技術,都需要一定的治理來維護數據的完整性,常用的方法是批處理維護、應用邏輯和觸發器。批處理維護是指對復制列或派生列的修改積累一定的時間后,運行一批處理作業或存儲過程對復制或派生列進行修改,這只能在對實時性要求不高的情況下使用。數據的完整性也可由應用邏輯來實現,這就要求必須在同一事務中對所有涉及的表進行增、刪、改操作。用應用邏輯來實現數據的完整性風險較大,因為同一邏輯必須在所有的應用中使用和維護,輕易遺漏,非凡是在需求變化時,不易于維護。另一種方式就是使用觸發器,對數據的任何修改立即觸發對復制列或派生列的相應修改。觸發器是實時的,而且相應的處理邏輯只在一個地方出現,易于維護。一般來說,是解決這類問題的最好的辦法。
4. 結束語
數據庫的反規范設計可以提高查詢性能。常用的反規范技術有增加冗余列、增加派生列、重新組表和分割表。但反規范技術需要維護數據的完整性。因此在做反規范時,一定要權衡利弊,仔細分析應用的數據存取需求和實際的性能特點。