1:在進行多表關聯(lián)時,多用 Where 語句把單個表的結果集最小化,多用聚合函數(shù)匯總結果集后再與其它表做關聯(lián),以使結果集數(shù)據(jù)量最小化
2:在兩張表進行關聯(lián)時,應考慮可否使用右連接。以提高查詢速度
3:使用 where 而不是 having ,where是用于過濾行的,而having是用來過濾組的,因為行被分組后,having 才能過濾組,所以盡量用戶 WHERE 過濾
4:使用 exists 而不用 IN 因為 Exists 只檢查行的存在,而 in 檢查實際值。
5:IN操作符
用 IN 寫出來的 SQL 的優(yōu)點是比較容易寫及清晰易懂,這比較適合現(xiàn)代軟件開發(fā)的風格。
但是用 IN 的 SQL 性能總是比較低,原因是:
對于用 IN 的 SQL 語句 ORACLE 總是試圖將其轉換成多個表的連接,如果轉換不成功則先執(zhí)行 IN
里面的子查詢,再查詢外層的表記錄
如果轉換成功就轉換成多個表的連接。因此 不管理怎么,用 IN 的 SQL 語句總是多了 一個轉換的
過程。一般的 SQL 都可以轉換成功。
但對于含有分組統(tǒng)計等方面的 SQL 就不能轉換了。因此在業(yè)務密集的SQL當中盡量不采用IN操作符。
6:NOT IN 操作符
此操作強烈推薦不使用,因為其不能應用表的索引。
如遇這種情況,應該用 EXISTS ,NOT EXISTS 或者(外連接+判斷為空)方案代替。
7:> 操作符
不等于操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。
對于這種情況,可以用其它方式代替,如:
A>0 -> A>0 OR A0
A>'' -> A>''
8:like 操作符
遇到 需要用到 LIKE 過濾的SQL語句,完全可以用 instr 代替。處理速度將顯著提高。
9:union操作符
union在進行表鏈接后會篩選掉重復的記錄,所以在表鏈接后會對所產生的結果集進行排序運算,
刪除重復的記錄再返回結果。實際大部分應用中是不會產生重復的記錄,最常見的是過程表與歷史
表union。如:
復制代碼 代碼如下:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重復的記錄,最后返回結果集,
如果表數(shù)據(jù)量大的話可能會導致用磁盤進行排序。
推薦方案:采用union ALL操作符替代union,因為union ALL操作只是簡單的將兩個結果合并后就返回。
復制代碼 代碼如下:
select * from gc_dfys
union all
select * from ls_jg_dfys
10 SQL書寫的影響
同一功能同一性能不同寫法SQL的影響
如一個SQL在A程序員寫的為
select * from zl_yhjbqk
B程序員寫的為
select * from dlyx.zl_yhjbqk(帶表所有者的前綴)
C程序員寫的為
select * from DLYX.ZLYHJBQK(大寫表名)
D程序員寫的為
select * from DLYX.ZLYHJBQK(中間多了空格)
以上四個SQL在ORACLE分析整理之后產生的結果及執(zhí)行的時間是一樣的,但是從ORACLE共享內存SGA的
原理,
可以得出ORACLE對每個SQL都會對其進行一次分析,并且占用共享內存,如果將SQL的字符串及格式寫
得完全相同則ORACLE只會分析一次,
共享內存也只會留下一次的分析結果,這不僅可以減少分析SQL的時間,而且可以減少共享內存重復的
信息,ORACLE也可以準確統(tǒng)計SQL的執(zhí)行頻率。
11:where后面的條件順序影響
where子句后面的條件順序對大數(shù)據(jù)量表的查詢會產生直接的影響,如
復制代碼 代碼如下:
select * from zl_yhjbqk where dy_dj = '1KV以下' and xh_bz=1
select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1KV以下'
以上兩個SQL中dy_dj(電壓等級)及xh_bz(銷戶標志)兩個字段都沒進行索引,所以執(zhí)行的時候都
是全表掃描,
第一條SQL的dy_dj = '1KV以下'條件在記錄集內比率為99%,而xh_bz=1的比率只為0.5%,
在進行第一條SQL的時候99%條記錄都進行dy_dj及xh_bz的比較,而在進行第二條SQL的時候0.5%條記錄
都進行dy_dj及xh_bz的比較,
以此可以得出第二條SQL的CPU占用率明顯比第一條低。
12:詢表順序的影響
在FROM后面的表中的列表順序會對SQL執(zhí)行性能影響,在沒有索引及ORACLE沒有對表進行統(tǒng)計分析的
情況下ORACLE會按表出現(xiàn)的順序進行鏈接,
由此因為表的順序不對會產生十分耗服務器資源的數(shù)據(jù)交叉。(注:如果對表進行了統(tǒng)計分析,
ORACLE會自動先進小表的鏈接,再進行大表的鏈接)
13:采用函數(shù)處理的字段不能利用索引,如:
復制代碼 代碼如下:
substr(hbs_bh,1,4)='5400',優(yōu)化處理:hbs_bh like ‘5400%'
trunc(sk_rq)=trunc(sysdate),優(yōu)化處理:
sk_rq>=trunc(sysdate) and sk_rqtrunc(sysdate+1)
進行了顯式或隱式的運算的字段不能進行索引,如:
復制代碼 代碼如下:
ss_df+20>50,優(yōu)化處理:ss_df>30
‘X'||hbs_bh>'X5400021452',優(yōu)化處理:hbs_bh>'5400021542'
sk_rq+5=sysdate,優(yōu)化處理:sk_rq=sysdate-5
hbs_bh=5401002554,優(yōu)化處理:hbs_bh=' 5401002554',注:此條件對hbs_bh 進行隱式的
to_number轉換,因為hbs_bh字段是字符型。
條件內包括了多個本表的字段運算時不能進行索引,如:
ys_df>cx_df,無法進行優(yōu)化
qc_bh||kh_bh='5400250000',優(yōu)化處理:qc_bh='5400' and kh_bh='250000'
14:應用ORACLE的HINT(提示)處理
提示處理是在ORACLE產生的SQL分析執(zhí)行路徑不滿意的情況下要用到的。它可以對SQL進行以下方
面的提示
目標方面的提示:
COST(按成本優(yōu)化)
RULE(按規(guī)則優(yōu)化)
CHOOSE(缺省)(ORACLE自動選擇成本或規(guī)則進行優(yōu)化)
SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
ALL_ROWS(所有的行盡快返回)
SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
FIRST_ROWS(第一行數(shù)據(jù)盡快返回)
select *
from xxx
where xxx;
select *
from xxx
where xxx
優(yōu)化器提示:用它的目的是提高SQL語句的響應時間,快速的先返回 n 行。
訪問路徑的提示
FULL: 執(zhí)行全表掃描
ROID: 根據(jù)ROWID進行掃描
INDEX: 根據(jù)某個索引進行掃描
select * from emp where deptno=200 and sal>300;
如果寫了多個,則ORACLE自動選擇最優(yōu)的哪個
select * from emp where deptno=200 and sal>300;
INDEX_JOIN: 如果所選的字段都是索引字段(是幾個索引的),那么可以通過索引連接就可訪問到數(shù)據(jù),而不需要訪問
表的數(shù)據(jù)。
select deptno,sal from emp
where deptno=20;
INDEX_FFS: 執(zhí)行快速全索引掃描
select count(*) from emp;
NO_INDEX: 指定不使用哪些索引
select * from emp where deptno=200
and sal>300;
AND_EQUAL: 指定合并兩個或以上索引檢索的結果(交集),最多不能超過5個
執(zhí)行方法的提示:
USE_NL(使用NESTED LOOPS方式聯(lián)合)
USE_MERGE(使用MERGE join方式聯(lián)合)
USE_HASH(使用HASH join方式聯(lián)合)
根據(jù)表出現(xiàn)在FROM中的順序,ORDERED使ORACLE依此順序對其連接.
例如:
SELECT A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C
WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;
將指定表與嵌套的連接的行源進行連接,并把指定表作為內部表.
例如:
SELECT BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM
FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
將指定的表與其他行源通過合并排序連接方式連接起來.
例如:
SELECT * FROM BSEMPMS,BSDPTMS
WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
將指定的表與其他行源通過哈希連接方式連接起來.
例如:
SELECT * FROM BSEMPMS,BSDPTMS
WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
其它高級提示(如并行處理等等)
ORACLE的提示功能是比較強的功能,也是比較復雜的應用,并且提示只是給ORACLE執(zhí)行的一個建議,
有時如果出于成本方面的考慮ORACLE也可能不會按提示進行。根據(jù)實踐應用,一般不建議開發(fā)人員應用ORACLE提示,
因為各個數(shù)據(jù)庫及服務器性能情況不一樣,很可能一個地方性能提升了,但另一個地方卻下降了,
ORACLE在SQL執(zhí)行分析方面已經比較成熟,如果分析執(zhí)行的路徑不對首先應在數(shù)據(jù)庫結構(主要是索引)、
服務器當前性能(共享內存、磁盤文件碎片)、數(shù)據(jù)庫對象(表、索引)統(tǒng)計信息是否正確這幾方面分析。
您可能感興趣的文章:- Oracle之SQL語句性能優(yōu)化(34條優(yōu)化方法)
- Oracle數(shù)據(jù)庫中基本的查詢優(yōu)化與子查詢優(yōu)化講解
- 關于Oracle多表連接,提高效率,性能優(yōu)化操作