序號 | 術語/縮略語 | 全稱和說明 |
---|---|---|
1 | 表(TABLE) | 數據庫中用於存儲數據的基本存儲單位 |
2 | 派生受權 | 給用戶受權時,使用with grant option,使得被受權的用戶能夠將被受權的對象受權給其它用戶 |
3 | 接口表 | 當經過goldengate或者ETL方式進行數據同步的時候, 在目標端建立的與源表結構一致的同構表。 |
4 | 基表 | 存放基礎數據, 配置數據的表, 這些數據僅提供給業務處理過程使用, 而不會在業務處理過程當中被修改。 基表中的數據很是穩定, 極少修改,也幾乎不會外鍵關聯到其它表。 |
2.1.1 表的設計必需要知足第一範式。 sql
在表設計中,不容許字段出現二義性。例如,表中不能有這樣的字段,字段的值是由幾位數字組成的代碼,第一位表示客戶類型,第二位表示渠道類型……,這種設計不符合第一範式,不容許出現。 數據庫
2.1.2 建議1:表的設計應儘可能知足第三範式。 緩存
數據庫三範式的說明請參見 附錄3.2 數據庫三範式說明。 jsp
2.2.1 create table語句參數不能包含storage選項,不能包含nologging選項, nologging 會影響數據庫的災備和恢復。 數據庫設計
例如:如下建表語句,tablespace後面的部分不能包含。 函數
create table AREA_DEFINE ( created_by varchar2(100), created_date date, updated_by varchar2(100), updated_date date, area_code varchar2(4) ) tablespace PCISBASE_DATA pctfree 10 initrans 1 maxtrans 255 storage ( initial 5M next 5M minextents 1 maxextents unlimited pctincrease 0 ) Nologging;
create table AREA_DEFINE ( created_by varchar2(100), created_date date, updated_by varchar2(100), updated_date date, area_code varchar2(4) ) ;
而在生產數據庫版本爲Oracle 9i時, 則在建表時須要加上MONITORING參數。
MONITORING參數說明:建立表時設置MONITORING參數, 使得Oracle跟蹤對錶的DML操做,預估DML操做所影響的記錄數量。在Oracle 9i中, MONITORING參數不是默認的,須要手工執行,而在Oracle 10g及以上版本中, 該參數爲默認設置。 工具
2.3.1 表中一條記錄全部字段的長度不能超過該數據庫的db_block_size大小 性能
當字段總長度大於數據的db_block_size時,會產生大量的行連接,影響到表訪問的效率,應當避免。所以在對錶設計時,要求字段總長度不能超過數據的db_block_size大小。 測試
字段的總長度計算方法爲全部字段長度相加的總和。 如以C_INFO_TEMPLATE表爲例,該表有8個字段, 它所在的庫的db_block_size爲8192. ui
COLUMN_NAME | DATA_TYPE | DATA_LENGTH |
---|---|---|
INFO_TEMPLATE_CODE | NUMBER | 22 |
CREATED_BY | VARCHAR2 | 100 |
CREATED_TIME | DATE | 7 |
UPDATED_BY | VARCHAR2 | 50 |
UPDATED_TIME | DATE | 7 |
INFO_TEMPLATE_NAME | VARCHAR2 | 100 |
SPECIAL_CASE_CODE | VARCHAR2 | 6 |
IS_TEMP | VARCHAR2 | 2 |
則該表的字段長度爲 22+100+7+100+7+50+6+2 = 294字節,知足規範。
能夠在生產環境中使用以下sql查詢表的長度:
select sum(data_length) as "total column length" from user_tab_columns where table_name='&table_name';
能夠在生產環境中使用以下sql獲取數據塊大小:
SQL> show parameter db_block_size
2.3.2 字段必須定義正確的數據類型
在設計表結構時,對於只存儲數字的字段應定義成數字類型,只存儲字符的字段定義成字符類型,只存儲日期的字段定義成日期類型,以減小使用過程當中的數據類型轉換。
好比有Customer表, 字段定義以下:
Column name | Type | Is Null? |
---|---|---|
Cust_no | Varchar2(50) | N |
Cust_name | Varchar2(255) | Y |
Date_birth | Varchar2(50) | Y |
sex | Varchar2(50) | Y |
其中錯誤的定義有:
Cust_no字段中只存儲數字。因此須要定義爲number, 不能定義爲varchar2。
date_birth字段應該定義爲date, 不能定義爲varchar2。
sex字段的定義過長,只須要定義varchar2(1)就能夠了,咱們記錄性別爲F(女)或M(男)。
2.3.3 在表中不容許使用Long類型字段; 可使用Lob數據類型字段, 但在Oracle 11g中, 必須使用secure file。
LOBs數據對象分爲兩類:
使用LOB類型, 有以下參數須要設置:
所以,在使用LOB字段時必須設置DISABLE STORAGE IN ROW。
僅在知足如下條件:
只有在最終結果集中會返回該數據行的LOB數據時, 纔會對該數據行所在的block進行讀取。 且知足如下兩個條件之一
a) 該表從不會與其它表關聯使用.
b) 若是有與其它表關聯,則老是經過主鍵或者索引進行關聯.
才使用ENABLE STORAGE IN ROW。
chuck設置 | 存儲LOB所佔用磁盤大小 | 磁盤利用率(%) | I/O讀取次數 |
---|---|---|---|
8K | 8K | 62.5 | 1 |
16K | 16K | 31.25 | 1 |
32K | 32K | 15.63 | 1 |
LOB size爲25K :
chuck設置 | 存儲LOB所佔用磁盤大小 | 磁盤利用率(%) | I/O讀取次數 |
---|---|---|---|
8K | 32K | 78.13 | 4 |
16K | 32K | 78.13 | 2 |
32K | 32K | 78.13 | 1 |
Db_Block_size: 8K | Db_Block_size: 16K | Db_Block_size: 32K | |
---|---|---|---|
LOB數據主要分佈區間在【0,8k】 | 8K | 16K | 32K |
LOB數據主要分佈區間在【8k,16k】 | 16K | 16K | 32K |
LOB數據主要分佈區間在【16k,32k】 | 32K | 32K | 32K |
LOB數據主要分佈區間大於32k | 32K | 32K | 32K |
若是有須要對存儲和性能進行綜合考慮,可在該表使用一段時間後, 對LOB字段數據狀況進行分析
可以使用下面的sql對LOB字段進行全表分析
《數據庫開發管理規範_全表分析LOB.rar》
若是LOB表數據量較大,也可以使用下面的sql對LOB字段進行採樣的分析
《採樣分析LOB說明.rar》
在Oracle 11g的Securefile 方式中, CHUNK 的最大值爲64MB,且會自動適應LOB數據的大小, 所以無需設置CHUNK參數。
舉例: 建立帶有LOB字段的表
create table customer ( id_customer raw(32), customer_name varchar2(100), customer_photo clob ) lob (customer_photo) store as ( tablespace hrmslobdata disable storage in row chunk 32k pctversion 10 nocache logging );
所以: 數據庫使用AL32UTF8字符集時:
LOB數據字節數= (漢字字符數*3 + 英文字符數*1 )/ ( 1 - PCT_FREE )
數據庫使用GBK時: LOB數據字節數= (漢字字符數*2 + 英文字符數*1 )/ ( 1 - PCT_FREE )
若是使用BLOB字段類型,BLOB數據長度與原二進制文件大小一致。
create table customer ( id_customer raw(32), customer_name varchar2(100), customer_photo blob ) lob (customer_photo) store as securefile ( tablespace hrmslobdata disable storage in row nocache logging );
Securefile用法和測試按列請見:附錄3.3。
2.3.4 表和字段必須有comment中文註釋
表和字段必須有中文註釋,註釋採用comment on的形式,如:
Comment on table AREA_DEFINE is ‘地區定義表’;
Comment on column AREA_DEFINE.AREA_CODE is ‘地區代碼’;
2.3.5 爲了保證表中數據的完整性,在設計表時,必須考慮給各字段加上適當的約束
約束的類型有非空約束,惟一性約束,主鍵約束,外鍵約束,check約束等;
Check 約束僅適用於Boolean類型字段的檢查需求, 或者是一些二元屬性的字段,好比表示性別字段,只有’F’,’M’ 兩種值,也可以使用Check約束。而對於其它的列值檢查必須採用基表+主外鍵的方式。
2.3.6 除日誌表、臨時表外,其它新建表中,必須有數據建立人,建立時間,修改人,修改時間這4個字段,四個必須字段異動的內容必須經過trigger方式實現,不能經過程序代碼實現,字段名及數據類型、長度須與下面的保持一致。
建立人 | created_by | varchar2(100) | not null; |
建立時間 | created_date | date | not null; |
修改人 | updated_by | varchar2(100) | not null; |
修改時間 | updated_date | date | not null; |
注意:這四個審計字段僅適用於記錄該表自身數據的變化,若是以該表爲目標表的源表須要同步審計字段信息,則要求該目標表新建四個審計字段存放源表數據,新字段命名需和目標表審計字段區分開來,參考示例:
源建立人 | src_created_by | varchar2(100) | not null; |
源建立時間 | src_created_date | date | not null; |
源修改人 | src_updated_by | varchar2(100) | not null; |
源修改時間 | src_updated_date | date | not null; |
2.3.7 對於經過UM登錄系統或者直接用腳原本操做數據的狀況,created_by,updated_by必須插入員工UM編碼 。
2.3.8 全部外鍵上都必須建立索引。
若沒有對外鍵創建索引,則在對父表DELETE操做或者UPDATE關聯父表的鍵值操做時,會對子表產生全表獨佔鎖,引起性能問題。
2.3.9 全部表必需要主鍵,除了temparory tablespace 中的臨時表之外.
2.3.10 建立主鍵時必須先建立索引,再建立主鍵。
先建立惟一索引,再基於該索引建立主鍵。
在刪除主鍵時若遺忘指定keep index,則刪除主鍵的同時會將主鍵索引也一併刪除。若仍然有SQL需使用該索引時就會引起性能問題,並且要重建該索引也可能須要花費較長時間。
所以需採用先建立索引再建立主鍵的方式,避免上述狀況的發生。
以CUSTOMER表爲例,如今要在ID字段建立主鍵
col_name | type | is_null |
---|---|---|
id_cust | varchar2(32) | N |
cust_name | varchar2(255) | Y |
date_birth | Date | Y |
sex | varchar2(1) | Y |
create unique index pk_customer_id on customer (id_cust); alter table customer add constraint pk_customer_id primary key (id_cust) using index pk_customer_id;
錯誤的腳本:
alter table customer add constraint pk_customer_id primary key (id_cust) ;
2.3.11 除接口表和基表的主鍵字段之外, 全部主鍵字段必須使用DB級 sys_guid值做爲pk值, 字段類型統一爲VARCHAR2(32)。對應子表的外鍵字段也應該使用VARCHAR2(32),保持類型相同。
例:
Insert into customer (id_cust, cust_name, date_birth, sex) values ( sys_guid() ,’Jimmy’,null,’M’);
2.3.12 選擇主鍵必須遵行的原則
col_name | type | is_null |
---|---|---|
phone_number | number(20) | N |
cust_id | number | N |
status | varchar2(1) | N |
date_register | date | N |
col_name | type | is_null |
---|---|---|
Id_ims_phone_number | varchar2(32) | N |
phone_number | number(20) | N |
cust_id | number | N |
status | varchar2(1) | N |
date_register | date | N |
col_name | type | is_null | description |
---|---|---|---|
id_cust | varchar2(32) | N | 客戶ID |
id_couse | varchar2(32) | N | 課程ID |
course_score | number | Y | 選修得分 |
id_cust字段與id_course字段這兩個字段是複合惟一的,但不能在這兩個字段上建立複合主鍵,而是須要增長一個字段id_cust_grade字段做爲主鍵, 使用SYS_GUID值作爲主鍵,字段類型爲varchar2(32)。而在id_cust和id_course兩個字段上建立惟一索引。以下:
col_name | type | is_null | description |
---|---|---|---|
id_cust_grade | varchar2(32) | N | ID |
id_cust | varchar2(32) | N | 客戶ID |
id_course | varchar2(32) | N | 課程ID |
course_score | number | Y | 選修得分 |
2.3.13 不容許修改表上已有的主鍵結構
表上的主鍵一旦肯定,將不容許被修改,由於修改主鍵將會帶來一系列的問題。
除非由於業務規則發生改變而致使不得不修改主鍵的狀況發生, 此時修改主鍵必須知足如下條件:
a) 新主鍵定義必需要知足規範2.3.12
b) 原主鍵定義不知足規範2.3.12.3
c) 原主鍵不是其它任何一張表的外鍵
當主鍵是其它子表的外鍵時,修改主鍵會致使以它做爲外鍵的子表上產生鎖,若是子表在這個外鍵上有索引,則會產生行鎖,若是沒有索引,則會產生表鎖。
刪除原有主鍵約束時,必須評估主鍵對應的索引是否須要保留, 若是不要保留,須要使用Quest SQL Optimizer工具的impact analyzer 進行對比測試,評估變動影響。
若刪除了主鍵而沒有保留索引,則根據原主鍵查詢的SQL語句將再也不走原主鍵的惟一索引,執行計劃發生改變,極有可能致使SQL出現性能問題,此時須要評估這種改變帶來的性能問題。
2.3.14 建議3: 全部業務上有主外鍵關係都必須在數據庫中建立主外鍵。
2.3.15 惟一鍵的建立方式,與主鍵相同,即先建索引,而後加惟一鍵
2.3.16 在修改表時,若是增長有default值的列或者修改字段的非空屬性,必須先作ddl增長字段,再作dml更新值,而後再作ddl增長字段的default屬性或非空屬性。但若是所修改數據庫是Oracle 11g版本,則無須此操做。
alter table test1 add is_lbs varchar2(6) default 'YES';
須要改成ddl,dml和ddl三個腳本:
alter table test1 add is_lbs varchar2(6); update test1 set is_lbs='YES' where ……; (該dml語句須要支持斷點續作和分段提交) alter table test1 modify is_lbs default ‘YES’;
修改表的某字段爲 not null,應該先將該列值爲空的記錄update爲非空,再增長not null約束。例如:對於某個table,修改字段A爲 not null :
update test set A=’’ where A is null ……; (該dml語句須要支持斷點續作和分段提交) alter table test modify A not null;
對錶增長有default值且not null的列,應該先作ddl增長字段,再作dml更新值。
例如:對於某個table,增長一個有default值且not null的列,須要將以下ddl:
alter table test1 add is_lbs varchar2(6) default ‘YES' not null;
改成ddl,dml和ddl三個腳本:
alter table test1 add is_lbs varchar2(6); update test1 set is_lbs='YES' where …...; (該dml語句須要支持斷點續作和分段提交 ) alter table test1 modify is_lbs default ‘YES’ not null;
對於表數據的備份,請參見《DML數據備份修改管理規範》。
alter table test1 modify is_lbs default ‘YES’ not null;
Oracle 11g 會把默認值存儲在數據字典中,而不須要先對錶作update操做
2.3.17 應用程序中若須要truncate表中的數據,必須採用DBA統一編寫的truncate_table過程來實現。不容許爲任何業務用戶授予drop any table的權限。
2.3.18 對於大表的定義: 將容量超過2G的表定義爲大表。
在數據庫設計時須要對大表考慮是否進行分區,數據清理,以及歸檔操做。
Student Advisor Adv-Room Class1 Class2 Class3
----------------------------------------------------------------------------------------------
1022 Jones 412 101-07 143-01 159-02
4123 Smith 216 201-01 211-02 214-01
一個student 會對應多個class, 但上表中使用class1,class2,class3 的設計方式會帶來麻煩。知足第一範式的設計應該爲:
Student Advisor Adv-Room Class
------------------------------------------------------------------
1022 Jones 412 101-07
1022 Jones 412 143-01
1022 Jones 412 159-02
4123 Smith 216 201-01
4123 Smith 216 211-02
4123 Smith 216 214-01
表中的數據只應該依賴於表的主鍵。例如在財務系統中客戶的地址, 會在客戶,訂單,發貨,發票,收賬的環節都須要。所以應該將客戶的地址放在單獨的一個表中,好比客戶表或者地址表。而不是將它在以上每個表都保存一份。繼續上面的例子,雖然已經知足第一範式,但注意到Class字段並非函數依賴主鍵student,不知足第二範式。須要將class拿出來和student 單獨組成一個表,以知足第二範式:
Student:
Student Advisor Adv-Room
-----------------------------------------------------
1022 Jones 412
4123 Smith 216
Registration:
Student Class
-------------------------------------
1022 101-07
1022 143-01
1022 159-02
4123 201-01
4123 211-02
4123 214-01
Student:
Student Advisor
----------------------------------
1022 Jones
4123 Smith
Faculty: Name Room Dept ----------------------------------------- Jones 412 42 Smith 216 42