1. EXISTS 替換 IN
儘可能少用IN操做符,基本上全部的IN操做符均可以用EXISTS代替
用IN寫出來的SQL的優勢是比較容易寫及清晰易懂,可是用IN的SQL性能老是比較低的,從ORACLE執行的步驟來分析用IN的SQL與不用IN的SQL有如下區別:
ORACLE 試圖將其轉換成多個表的鏈接,若是轉換不成功則先執行IN裏面的子查詢,再查詢外層的表記錄,
若是轉換成功則直接採用多個表的鏈接方式查詢。因而可知用 IN的SQL至少多了一個轉換的過程。通常的SQL均可以轉換成功,但對於含有分組統計等方面的SQL就不能轉換了。數據庫
Oracle在執行IN子查詢時,首先執行子查詢,將查詢結果放入臨時表再執行主查詢。而EXIST則是首先檢查主查詢,而後運行子查詢直到找到第一個匹配項。
NOT EXISTS比NOT IN效率稍高。但具體在選擇IN或EXIST操做時,要根據主子表數據量大小來具體考慮。
推薦方案:在業務密集的SQL當中儘可能不採用IN操做符。
不用NOT IN操做符,能夠用NOT EXISTS或者外鏈接+替代
此操做是強列推薦不使用的,由於它不能應用表的索引。
推薦方案:用NOT EXISTS 或(外鏈接+判斷爲空)方案代替分佈式
不用「<>」或者「!=」操做符。對不等於操做符的處理會形成全表掃描,能夠用「<」 or 「>」代替 2. 不等於替換
不等於操做符是永遠不會用到索引的,所以對它的處理只會產生全表掃描。
推薦方案:用其它相同功能的操做運算代替,如:
1)a<>0 改成 a>0 or a<0
2)a<>’’ 改成 a>’’ide
3. NULL 值
Where子句中出現IS NULL或者IS NOT NULL時,Oracle會中止使用索引而執行全表掃描。能夠考慮在設計表時,對索引列設置爲NOT NULL。
這樣就能夠用其餘操做來取代判斷NULL的操做 IS NULL 或IS NOT NULL操做(判斷字段是否爲空)
判斷字段是否爲空通常是不會應用索引的,由於B樹索引是不索引空值的。
推薦方案:
用其它相同功能的操做運算代替,如:
1)a is not null 改成 a>0 或a>’’等。
2)不容許字段爲空,而用一個缺省值代替空值,如業擴申請中狀態字段不容許爲空,缺省爲申請。
3) 創建位圖索引(有分區的表不能建,位圖索引比較難控制,如字段值太多索引會使性能降低,多人更新操做會增長數據塊鎖的現象)
4. LIKE 通配符
1> 當通配符「%」或者「_」做爲查詢字符串的第一個字符時,索引不會被使用;
2> 使用帶有前導字段的LIKE 來替換SUBSTR 函數.
3> LIKE 操做符能夠應用通配符查詢,裏面的通配符組合可能達到幾乎是任意的查詢,可是若是用得很差則會產生性能上的問題,
如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來
查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,若是改爲YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引
進行兩個範圍的查詢,性能確定大大提升。
對於有鏈接的列「||」,最後一個鏈接列索引會無效。儘可能避免鏈接,能夠分開鏈接或者使用不做用在列上的函數替代。函數
5.不一樣數據類型比較
對數據類型不一樣的列進行比較時,會使索引失效。
> 及 < 操做符(大於或小於操做符)
大於或小於操做符通常狀況下是不用調整的,由於它有索引就會採用索引查找,但有的狀況下能夠對它進行優化,如一個表有100萬記錄,
一個數值型字段A, 30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那麼執行A>2與A>=3的效果就有很大的區別了,
由於 A>2時ORACLE會先找出爲2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。
推薦方案:用「>=」替代「>」。性能
6.UNION操做符
UNION在進行表連接後會篩選掉重複的記錄,因此在表連接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。
實際大部分應用中是不會產生重複的記錄,最多見的是過程表與歷史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,若是表數據量大的話可能會致使用磁盤進行排序。
推薦方案:採用UNION ALL操做符替代UNION,由於UNION ALL操做只是簡單的將兩個結果合併後就返回。
select * from gc_dfys
union all
select * from ls_jg_dfys優化
7.多表查詢順序
兩個表聯合查詢,數據量小的表放最後,三個以表聯合查詢,交叉表放最後.spa
8.函數
若是索引不是基於函數的,那麼當在Where子句中對索引列使用函數時,索引再也不起做用。
Where子句中避免在索引列上使用計算,不然將致使索引失效而進行全表掃描。設計
9.對條件字段的一些優化
採用函數處理的字段不能利用索引
如: substr(hbs_bh,1,4)=’5400’,優化處理:hbs_bh like ‘5400%’
trunc(sk_rq)=trunc(sysdate), 優化處理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)
進行了顯式或隱式的運算的字段不能進行索引
如:ss_df+20>50,優化處理:ss_df>30
‘X’||hbs_bh>’X5400021452’,優化處理:hbs_bh>’5400021542’
sk_rq+5=sysdate,優化處理:sk_rq=sysdate-5
hbs_bh=5401002554,優化處理:hbs_bh=’ 5401002554’,注:此條件對hbs_bh 進行隱式的to_number轉換,由於hbs_bh字段是字符型。
條件內包括了多個本表的字段運算時不能進行索引
ys_df>cx_df,沒法進行優化
qc_bh||kh_bh=’5400250000’,優化處理:qc_bh=’5400’ and kh_bh=’250000’
10.其它
1> 減小對錶的鏈接次數(減小邏輯讀) 列UPDATE
2> 刪除表數據時儘可能使用TRUNCATE 替代DELETE.
3> 若是須要在PL/SQL程序中使用動態SQL,建議使用EXECUTE IMMEDIATE;
4> 考慮使用非惟一索引支持惟一性約束條件.
5> 在分佈式數據庫中,儘可能避免遠程訪問.
6> 主動的確認使循環嵌套,合併鏈接,散列鏈接.
排序