數據庫設計(Database Design)是指對於一個給定的應用環境,構造最優的數據庫模式,建立數據庫及其應用系統,使之能夠有效地存儲數據,滿足各種用戶的應用需求(信息要求和處理要求)。
一、數據庫設計的原則
1. 表設計原則
(1)規范化與反規范化
規范化的優點是減少了數據冗余,節約了存儲空間,相應邏輯和物理的I/O次數減少,同時加快了增、刪、改的速度。但是一個完全規范化的設計並不總能生成最優的性能,因為對數據庫查詢通常需要更多的連接操作,從而影響到查詢的速度,而且范式越高性能就會越差。出於性能和方便管理的考慮,原則上表設計應滿足第三范式。有時為了提高某些查詢或應用的性能而可以破壞規范規則,即反規范化。
數據應當按兩種類別進行組織:頻繁訪問的數據和頻繁修改的數據。對於頻繁訪問但是不頻繁修改的數據,內部設計應當物理不規范化。對於頻繁修改但並不頻繁訪問的數據,內部設計應當物理規范化。比較復雜的方法是將規范化的表作為邏輯數據庫設計的基礎,然后再根據整個應用系統的需要,物理地非規范化數據。
(2)數據表分類說明
根據應用的實際需要和特點,可以將數據表進行如下分類:
l 基本數據表:描述業務實體的基本信息。例如,人員基本信息、單位基本信息等。
l 標准編碼表:描述屬性的列表值。例如,職稱、民族、狀態等。
l 業務數據表:記錄業務發生的過程和結果。例如,人員調動登記、變更通知單等。
l 系統信息表:存放與系統操作、業務控制有關的參數。例如,用戶信息、權限、用戶配置信息等。
l 統計數據表:存放業務數據統計值。例如,通知單統計、人員類別統計等。
l 臨時處理表:存放業務處理過程中的中間結果。
l 其他類型表:存放應用層的日志、消息記錄等。
2. 字段設計原則
(1)一般來說,應該使用能正確存儲和表示數據的最小類型。如果不確定需要什么數據類型,則選擇不會超出范圍的最小類型。
(2)選擇更簡單的數據類型。例如,比較整數的代價小於比較字符,因為字符集和排序規則使字符比較更復雜。
(3)盡可能把字段定義為 NOT NULL。對於字段能否NULL,應該在SQL建表腳本中明確指明,不應使用缺省。
(4)一個表中的字段不要太多,理論上不要超過80個。
(5)數據庫中所有布爾型中數值0表示為假;數值1表示為真
(6)當字段定義為字符串類型時使用VARCHAR2而不用NVARCHAR
(7)字段盡可能有默認值,字符型的默認值為一個空字符值串,數字型的默認值為數值0。
3. 鍵設計原則
(1)為關聯字段創建外鍵。
(2)所有的鍵都必須唯一。
(3)盡可能避免使用復合鍵。
(4)外鍵總是關聯唯一的鍵字段。
(5)盡可能使用系統生成(如序列SEQUENCE產生)的主鍵。
(6)可選鍵有時可做主鍵。
(7)一個表中組合主鍵的字段個數盡可能少。
4. 索引設計原則
(1)如果一列出現在表達式或函數中,不會使用該列上的索引
(2)要索引外鍵
(3)對於索引選擇性高的列使用B-Tree索引
(4)對於索引選擇性低的列使用位圖索引
(5)HASH索引只適用於相等比較
(6)不要索引大型字段(有很多字符的字段)
(7)不要索引常用的小型表
5. LOB設計原則
如無特別需要,避免使用大字段(BLOB、CLOB、LONG等)。如使用時必須使用BLOB或CLOB類型。
二、完整性設計
采用數據庫系統實現數據的完整性。這不但包括通過標准化實現的完整性而且還包括數據的功能性。在寫數據的時候還可以增加觸發器來保證數據的正確性。不要依賴於應用程序保證數據完整性,它不能保證表之間(外鍵)的完整性。
1.主鍵約束
每個表要求有主健,主健字段或組合字段必須滿足非空屬性和唯一性要求。
2.外鍵約束
(1)對於關聯兩個表的字段,一般應該分別建立主鍵、外鍵。實際是否建立外鍵,根據對數據完整性的要求決定。
(2)根據需要適當設置父表數據修改時對子表的影響:
l 父表中刪除數據:級聯刪除;受限刪除;置空值。
l 父表中插入數據:受限插入;遞歸插入。
l 父表中更新數據:級聯更新;受限更新;置空值。
3.NULL值
由於NULL值在參加任何運算時,結果均為NULL,所以必須利用NVL()函數把可能為NULL值得字段或變量轉換為非NULL的默認值。
4.CHECK條件
對於字段有檢查性約束,要求指定CHECK規則。
5.觸發器
觸發器是一種特殊的存儲過程,通過對表的DML操作而觸發執行,是為確保數據的完整性和一致性不被破壞而創建,實現數據的完整約束。選擇觸發器的BEFORE或AFTER事務屬性的時候,對表操作的事務屬性必須與應用程序事務屬性保持一致,以避免死鎖發生。在大量修改數據時,盡量避免使用觸發器。
6.視圖
為了在數據庫和應用程序之間提供另一層抽象,可以為應用程序建立專門的視圖而不必非要應用程序直接訪問表。這樣做還在處理數據庫變更時提供了更多的自由。視圖是虛擬的數據庫表,在使用時要遵循以下原則:
l 為簡化查詢,將復雜的檢索或子查詢通過視圖實現。
l 提高數據的安全性,只將需要查看的數據信息顯示給權限有限的人員。
l 視圖中如果嵌套使用視圖,級數不要超過3級。
l 由於視圖中只能固定條件或沒有條件,所以對於數據量較大或隨時間的推移逐漸增多的表,不宜使用視圖,可以采用實體化視圖代替。
l 除特殊需要,避免類似SELECT * FROM [TableName] 而沒有檢索條件的視圖。
l 視圖中盡量避免出現數據排序的SQL語句。
三、命名規范
1.總則
(1)所有命名采用26個英文大小寫字母和0-9這十個自然數,加上下划線_組成。不能出現其他字符(注釋除外)。
(2)長度不超過30個字符。
(3)實際名字盡量描述實體的內容,由英文單詞、單詞組合或單詞縮寫組成,不以數字和_開頭。
(4)命名中禁止使用SQL關鍵字。
(5)對象名盡量短。
2.表
表以單數形式名詞或名詞短語命名。如果表名僅有一個單詞,那么建議不使用縮寫,而是用完整的單詞。
數據表 t_inf_<系統標識>_<表標識>
編碼表 t_cod_<系統標識>_<表標識>
系統表 t_sys_<系統標識>_<表標識>
統計表 t_sta_<系統標識>_<表標識>
臨時表 t_tmp_<系統標識>_<表標識>
日志表 t_log_<系統標識>_<表標識>
3.字段
l 采用有意義的字段名,應該是易於理解,能表達字段功能的英文單詞或單詞縮寫,一般不超過三個英文單詞。
l 系統中所有屬於內碼的字段(僅用於表示唯一性和程序內部用到的標識性字段),名稱取為:ID。
l 系統中屬於是業務范圍內的編號的字段,其代表一定的業務信息,這樣的字段建議命名為CODE,其數據類型為VARCHAR,該字段需加唯一索引。
l 字段名不要與表名重復
l 不要在列的名稱中包含數據類型。
4.主鍵
PK_<表名>
5.外鍵
FK_<表名>_<主表名>_<外鍵字段名>
6.索引
IDX_<表名>_<構成索引的字段名>
如果復合索引的構成字段較多,則只包含第一個字段,並添加序號。
7.視圖
V_<系統標識>_<視圖標識>
8.存儲過程
SP_<系統標識>_<存儲過程標識>
9.函數
F_<系統標識>_<函數標識>
10. 觸發器
TR_<表名>_<i、u、d的任意組合>
11. 用戶定義數據類型
UD_<自定義數據類型標識>
12. 序列
SEQ_<序列標識>
13. 局部變量
L_<變量標識>
14. 全局變量
G_<變量標識>
15. 游標變量
L_CUR_<變量標識>或G_CUR_<變量標識>
16. 存儲過程或函數定義中的參數
IN型參數:P_<參數標識>
OUT型參數:R_<參數標識>
函數返回值:R_<變量標識>
四、安全性設計
1.管理默認用戶
在生產環境中,必須嚴格管理SYS和SYSTEM用戶,必須修改其默認密碼,禁止用該用戶建立應用數據庫對象。刪除或鎖定SCOTT等默認安裝但不使用的用戶。
2.數據庫級用戶權限設計
必須按照應用需求,設計不同的用戶訪問權限。包括應用系統管理用戶,普通用戶等,按照業務需求建立不同的應用角色。用戶訪問另外的用戶對象時,應該通過創建同義詞對象SYNONYM進行訪問。
3.角色與權限
確定每個角色對數據庫表的操作權限,如創建、檢索、更新、刪除等。每個角色擁有剛好能夠完成任務的權限,不多也不少。在應用時再為用戶分配角色,則每個用戶的權限等於他所兼角色的權限之和。
4.應用級用戶設計
應用級的用戶帳號密碼不能與數據庫相同,防止用戶直接操作數據庫。用戶只能用帳號登錄到應用軟件,通過應用軟件訪問數據庫,而沒有其它途徑操作數據庫。
5.用戶密碼管理
用戶帳號的密碼必須進行加密處理,確保在任何地方查詢都不會出現密碼的明文。
五、SQL語句編寫
1.字符類型數據
SQL中的字符類型數據應該統一使用單引號。特別對純數字的字符串,必須用單引號,否則會導致內部轉換而引起性能問題或索引失效問題。利用TRIM(),LOWER()等函數格式化匹配條件。
2.復雜SQL
對於非常復雜的SQL(特別是有多層嵌套,帶子句或相關子查詢的),應該先考慮是否設計不當引起的。對於一些復雜SQL可以考慮使用程序實現。
3.避免IN子句
使用 IN 或 NOT IN 子句時,特別是當子句中有多個值且表數據較多時,速度會明顯下降。可以采用連接查詢或外連接查詢來提高性能。
4.避免使用SELECT * 語句
如果不必要取出所有數據,不要用 * 來代替,應給出字段列表。
5.避免不必要的排序
不必要的數據排序大大的降低系統性能。
6.INSERT語句
使用INSERT語句一定要給出插入值的字段列表,這樣即使表加了字段也不會影響現有系統的運行。
7.多表連接
做多表操作時,應該給每個表取一個別名,每個表字段都應該標明其所屬哪個表。
8.參數的傳遞
SQL語句的編寫,變量盡量使用“?”綁定變量。
9.存儲過程、函數中的注釋,示例如下:
/*
目的:
作者:
創建日期:
*/
/*
修改順序號:
修改者:
修改日期:
修改原因:(具體原因詳細描述)
*/
六、建模管理方法
1.建模工具
統一使用PowerDesigner軟件建模。推薦版本PowerDesigner 15中文版。
2.建模步驟
(1)邏輯建模
根據數據庫設計和命名規范先在PowerDesigner中建立邏輯模型(LDM)文件。要求每個表和字段都要有注釋說明;Check Model不能出現錯誤。
(2)根據邏輯模型文件創建對應數據庫的物理模型文件。
(3)生成數據庫結構及其相應的SQL腳本。
3.模型維護
(1)所有關於數據庫的表、字段及關系、說明等均以物理模型文件為准。
(2)由開發人員將變更需求提交項目負責人審批。
(3)項目負責人同意變更后由相應開發人員負責編寫變更腳本提交DBA。
(4)DBA更新數據庫及其相關文檔,並維護所有部分的一致性。
七、其他設計技巧
1.避免使用觸發器
觸發器的功能通常可以用其他方式實現。在調試程序時觸發器可能成為干擾。假如確實需要采用觸發器,最好集中對它文檔化。
2.保存常用信息
讓一個表專門存放一般數據庫信息非常有用。在這個表里存放數據庫當前版本、最近檢查/修復、關聯設計文檔的名稱、客戶等信息。這樣可以實現一種簡單機制跟蹤數據庫。
3.包含版本機制
在數據庫中引入版本控制機制來確定使用中的數據庫的版本。時間一長,用戶的需求總是會改變的。最終可能會要求修改數據庫結構。把版本信息直接存放到數據庫中更為方便。
4.編制文檔
對所有的命名規范、限制、數據字典、存儲過程、函數都要編制文檔。采用給表、列、觸發器等加注釋的數據庫工具。對開發、支持和跟蹤修改非常有用。對數據庫文檔化也會大大減少犯錯的機會。
5.測試、測試、反復測試
建立或者修訂數據庫之后,必須用用戶新輸入的數據測試修改的字段。最重要的是,讓用戶進行測試並且同用戶一起保證選擇的數據類型滿足要求。測試需要在把新數據庫投入實際服務之前完成。
6.檢查設計
在開發期間檢查數據庫設計的常用技術是通過其所支持的應用程序原型檢查數據庫。換句話說,針對每一種最終表達數據的原型應用,保證檢查了數據模型並且查看如何取出數據。