數據庫設計簡述 數據庫設計是把現實世界的商業模型與需求轉換成數據庫的模型的過程
它是建立數據庫應用系統的核心問題
設計的關鍵是如何使設計的數據庫能合理地存儲用戶的數據
方便用戶進行數據處理
數據庫設計完全是人的問題
而不是數據庫管理系統的問題
系統不管設計是好是壞
照樣運行
數據庫設計應當由數據庫管理員和系統分析員一起和用戶一道工作
了解各個用戶的要求
共同為整個數據庫做出恰當的
完整的設計
數據庫及其應用的性能和調優都是建立在良好的數據庫設計的基礎上
數據庫的數據是一切操作的基礎
如果數據庫設計不好
則其它一切調優方法提高數據庫性能的效果都是有限的
數據的規范化
范式概述
規范化理論是研究如何將一個不好的關系模式轉化為好的關系模式的理論
規范化理論是圍繞范式而建立的
規范化理論認為
一個關系數據庫中所有的關系
都應滿足一定的規范(約束條件)
規范化理論把關系應滿足的規范要求分為幾級
滿足最低要求的一級叫做第一范式(
NF)
在第一范式的基礎上提出了第二范式(
NF)
在第二范式的基礎上又提出了第三范式(
NF)
以後又提出了BCNF范式
NF
NF
范式的等級越高
應滿足的約束集條件也越嚴格
規范的每一級別都依賴於它的前一級別
例如若一個關系模式滿足
NF
則一定滿足
NF
下面我們只介紹
NF
NF
NF范式
NF
NF是關系模型的最低要求
它的規則是
每一列必須是原子的
不能分成多個子列
每一行和列的位置只能有一個值
不能具有多值列
例
如果要求一個學生一行
一個學生可選多門課
則下面的
學生
表就不滿足
NF
student(s-no
s-name
class-no)
其中
s-no為學號
s-name為學生姓名
class-no為課程號
因為一個學生可選多門課
所以列class-no有多個值
所以空不符合
NF
規范化就是把它分成如下兩個表
學生
表和
選課
表
則這兩個表就都滿足
NF了
student(s-no
s-name)
stu-class(s-no
class-no)
NF
對於滿足
NF的表
除滿足
NF外
非主碼的列必須依賴於所有的主碼
而不是組合主碼的一部分
如果滿足
NF的表的主碼只有一列
則它自動滿足
NF
例
下面的
選課
表
不符合
NF
stu-class(s-no
class-no
class-name)
其中
class-name為課程名稱
因為詞表的主碼是
(s-no
class-no)
非主碼列class-name依賴於組合主碼的一部分class-no
所以它不符合
NF
對該表規范化也是把它分解成兩個表
選課
表和
課程
表
則它們就都滿足
NF了
stu-class(s-no
class-no)
class(class-no
class-name)
NF
NF的規則是除滿足
NF外
任一非主碼列不能依賴於其它非主碼列
例
下面的
課程
表
不符合
NF
class(class-no
class-name
teacher-no
teacher-name)
其中
teacher-no為任課教師號
teacher-name為任課教師姓名
因為非主碼列teacher-name依賴於另一非主碼列teacher-no
所以它不符合
NF
其解決辦法也是把它分解成兩個表
課程
表和
教師
表
則它們就都滿足
NF了
class(class-no
class-name
teacher-no)
teacher(teacher-no
teacher-name)
小結
當一個表是規范的
則其非主碼列依賴於主碼列
從關系模型的角度來看
表滿足
NF最符合標准
這樣的設計容易維護
一個完全規范化的設計並不總能生成最優的性能
因此通常是先按照
NF設計
如果有性能問題
再通過反規范來解決
數據庫中的數據規范化的優點是減少了數據冗余
節約了存儲空間
相應邏輯和物理的I/O次數減少
同時加快了增
刪
改的速度
但是對完全規范的數據庫查詢
通常需要更多的連接操作
從而影響查詢的速度
因此
有時為了提高某些查詢或應用的性能而破壞規范規則
即反規范
數據的反規范 反規范的好處
是否規范化的程度越高越好?這要根據需要來決定
因為
分離
越深
產生的關系越多
關系過多
連接操作越頻繁
而連接操作是最費時間的
特別對以查詢為主的數據庫應用來說
頻繁的連接會影響查詢速度
所以
關系有時故意保留成非規范化的
或者規范化以後又反規范了
這樣做通常是為了改進性能
例如帳戶系統中的
帳戶
表B-TB
它的列busi-balance(企業帳戶的總余額)就違反規范
其中的值可以通過下面的查詢獲得
select busi-code
sum(acc-balance)
from B-TB
group by busi-code
如果B-TB
中沒有該列
若想獲得busi-name(企業名稱)和企業帳戶的總余額
則需要做連接操作
select busi-name
sum(acc-balance)
from B-TB
B-TB
where B-TB
busi-code=B-TB
busi-code
group by busi-code
如果經常做這種查詢
則就有必要在B-TB
中加入列busi-balance
相應的代價則是必須在表B-TB
上創建增
刪
改的觸發器來維護B-TB
表上busi-balance列的值
類似的情況在決策支持系統中經常發生
反規范的好處是降低連接操作的需求
降低外碼和索引的數目
還可能減少表的數目
相應帶來的問題是可能出現數據的完整性問題
加快查詢速度
但會降低修改速度
因此決定做反規范時
一定要權衡利弊
仔細分析應用的數據存取需求和實際的性能特點
好的索引和其它方法經常能夠解決性能問題
而不必采用反規范這種方法
常用的反規范技術
在進行反規范操作之前
要充分考慮數據的存取需求
常用表的大小
一些特殊的計算(例如合計)
數據的物理存儲位置等
常用的反規范技術有增加冗余列
增加派生列
重新組表和分割表
增加冗余列
增加冗余列是指在多個表中具有相同的列
它常用來在查詢時避免連接操作
例如前面例子中
如果經常檢索一門課的任課教師姓名
則需要做class和teacher表的連接查詢
select class-name
teacher-name
from class
teacher
where class
teacher-no=teacher
teacher-no
這樣的話就可以在class表中增加一列teacher-name就不需要連接操作了
增加冗余列可以在查詢時避免連接操作
但它需要更多的磁盤空間
同時增加表維護的工作量
增加派生列
增加派生列指增加的列來自其它表中的數據
由它們計算生成
它的作用是在查詢時減少連接操作
避免使用集函數
例如前面所講的賬戶系統中的表B-TB
的列busi-balance就是派生列
派生列也具有與冗余列同樣的缺點
重新組表
重新組表指如果許多用戶需要查看兩個表連接出來的結果數據
則把這兩個表重新組成一個表來減少連接而提高性能
例如
用戶經常需要同時查看課程號
課程名稱
任課教師號
任課教師姓名
則可把表class(class-no
class-name
teacher-no)和表teacher(teacher-no
teacher-name)合並成一個表class(class-no
class-name
teacher-no
teacher-name)
這樣可提高性能
但需要更多的磁盤空間
同時也損失了數據在概念上的獨立性
分割表
有時對表做分割可以提高性能
表分割有兩種方式
水平分割
根據一列或多列數據的值把數據行放到兩個獨立的表中
水平分割通常在下面的情況下使用:A 表很大
分割後可以降低在查詢時需要讀的數據和索引的頁數
同時也降低了索引的層數
提高查詢速度
B 表中的數據本來就有獨立性
例如表中分別記錄各個地區的數據或不同時期的數據
特別是有些數據常用
而另外一些數據不常用
C 需要把數據存放到多個介質上
例如法規表law就可以分成兩個表active-law和inactive-law
activea-authors表中的內容是正生效的法規
是經常使用的
而inactive-law表則使已經作廢的法規
不常被查詢
水平分割會給應用增加復雜度
它通常在查詢時需要多個表名
查詢所有數據需要union操作
在許多數據庫應用中
這種復雜性會超過它帶來的優點
因為只要索引關鍵字不大
則在索引用於查詢時
表中增加兩到三倍數據量
查詢時也就增加讀一個索引層的磁盤次數
垂直分割
把主碼和一些列放到一個表
然後把主碼和另外的列放到另一個表中
如果一個表中某些列常用
而另外一些列不常用
則可以采用垂直分割
另外垂直分割可以使得數據行變小
一個數據頁就能存放更多的數據
在查詢時就會減少I/O次數
其缺點是需要管理冗余列
查詢所有數據需要join操作
反規范技術需要維護數據的完整性 無論使用何種反規范技術
都需要一定的管理來維護數據的完整性
常用的方法是批處理維護
應用邏輯和觸發器
批處理維護是指對復制列或派生列的修改積累一定的時間後
運行一批處理作業或存儲過程對復制或派生列進行修改
這只能在對實時性要求不高的情況下使用
數據的完整性也可由應用邏輯來實現
這就要求必須在同一事務中對所有涉及的表進行增
刪
改操作
用應用邏輯來實現數據的完整性風險較大
因為同一邏輯必須在所有的應用中使用和維護
容易遺漏
特別是在需求變化時
不易於維護
另一種方式就是使用觸發器
對數據的任何修改立即觸發對復制列或派生列的相應修改
觸發器是實時的
而且相應的處理邏輯只在一個地方出現
易於維護
一般來說
是解決這類問題的最好的辦法
結束語 數據庫的反規范設計可以提高查詢性能
常用的反規范技術有增加冗余列
增加派生列
重新組表和分割表
但反規范技術需要維護數據的完整性
因此在做反規范時
一定要權衡利弊
仔細分析應用的數據存取需求和實際的性能特點
From:http://tw.wingwit.com/Article/program/Oracle/201311/16946.html