建表的幾條原則
表數(shù)據(jù)量是隨著時間持續(xù)增加(像訂單類表),并且運行一年后,表記錄數(shù)超過2000萬條,則需要考慮表分區(qū)。如果表數(shù)據(jù)基本上是靜態(tài)的(像用戶信息表),一般不考慮分區(qū)。如果記錄數(shù)接近億條,則可以考慮用HASH分區(qū)。表名只能使用字母、數(shù)字和下劃線,字母都小寫。數(shù)據(jù)庫里若存在多個用戶,則以用戶名簡寫開頭,比如用戶庫的表以USR_開頭,訂單庫的表以O(shè)RD_開頭;若只有一個用戶,則以t(表)或v(視圖)開頭。臨時表以tmp_開頭;備份表以bak_開頭。表的字段數(shù)量不超過30個,在非必要的情況下不要使用clob等大字段。一張表里所有字段的總長度盡量小,絕對不要超過8000(數(shù)據(jù)塊大小就是8K)。不同表里相同意義的字段,取名一樣。列如A表的更新時間字段取名update_time,那B表就不要再取名modify_time。選擇字段類型的時候,能用number就不要用varchar2。做查詢的時候,同等條件的number效率比varcha2高。值為枚舉型值的字段,用number(1)或者char(1);如果有超過10個以上的枚舉值,用char(2)。多個表里該類字段的值定義要一致。如a表status=0表示正常,則b表也應(yīng)一樣定義。這里可以約定一下:用char做類型時,值為A、B、C這樣的字母類型;用number做類型時,值為0-9,這樣方便區(qū)分。字段盡量設(shè)置為not null,或者設(shè)置默認值。表和字段,都需要有comment,尤其是枚舉型值字段。在mysql中,每個表都會有一個id字段做主鍵,也就是聚簇索引,其它的輔助索引都要通過聚簇索引來查詢。在oracle中,所有的索引都是通過rowid直接查詢的,不存在“二次查詢”,所有如果該id字段不與其他表做管理,則在表設(shè)計時不需要該字段。將表數(shù)據(jù)和索引數(shù)據(jù)分開存儲。建索引時明確指定表空間。索引數(shù)量不宜過多,一般情況下4個以內(nèi);索引太多會影響記錄的插入。個人認為為了限制記錄的唯一性時,可以建唯一索引;否則如果幾個字段均有可能作為查詢條件時,可以分成多個索引。復(fù)合索引字段的先后順序很重要,第一個字段必須是查詢時使用最頻繁的,否則有可能用不到索引。舉個不恰當(dāng)?shù)睦樱河脩粜畔⒈砝镉凶C件類型(cert_type)和證件號碼(cert_no),建唯一索引的時候,索引字段順序肯定是需要cert_no,cert_type,而不是cert_type, cert_no。因為查詢的時候,很有可能只是用了cert_no,而沒用到cert_type。我說“不恰當(dāng)”,是因為oracle的CBO比較厲害,在使用cert_type,cert_no作為復(fù)合索引的時候,oracle會分析后以跳躍索引處理,仍然能用到索引。SQL基本規(guī)范
錯誤用法:to_char(create_time)>’20220101’
正確用法:create_time>to_date(‘20220101’,’yyyymmdd’)+0.999
說明:create_time為date類型,如果create_time字段有索引,加了函數(shù)就會用不到索引。
比如,status為char(1),就不要寫成status=1,而是status=’1’。否則后續(xù)若status字典值擴展了,用了字母,sql就會報錯。
- 索引列字段不用函數(shù),查詢時要盡可能將函數(shù)操作移至等號右邊。
- 盡量避免使用order by和group by排序操作,大量的排序操作影響性能。如必須使用排序操作,盡量用在有索引的列上。
- 數(shù)據(jù)清理時的注意點:
做delete或update數(shù)據(jù)時,首先要select count(*)一下,計算一下受影響的記錄數(shù)。如果受影響記錄數(shù)是百萬級的,或者查詢條件是全表掃描的,那務(wù)必在查詢條件增加個rownum<=10000,一次影響1萬條。舉例1:(刪除500萬行記錄)declare
i integer:=500;
begin
while i>0 loop
delete from oper_log t where t.create_time<to_date('20220228','yyyymmdd') and rownum<=10000;
commit;
i := i-1;
end loop;
end;
舉例2:(按天清理數(shù)據(jù)到備份表)declare
i integer:=200;
mindate varchar2(8) :=’20211001′;
maxdate varchar2(8) :=’20211231′;
currdate varchar2(8) := mindate;
begin
while currdate <= maxdate loop
insert into bak_oper_log
select * from oper_log t where t.create_time<to_date(currdate,'yyyymmdd');
delete from oper_log t where t.create_time<to_date(currdate,'yyyymmdd');
commit;
currdate := to_char(to_date(currdate,’yyyymmdd’)+1,’yyyymmdd’);
end loop;
end;
鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。