數據庫SQL性能優化

 

1.in與exists的效率比較sql

in是把外表和內表做hash 鏈接,而exists 是對外表做loop 循環,每次loop 循環再對內表進行查詢。一直以來認爲exists 比in 效率高的說法是不許確的。若是查詢的兩個表大小至關,那麼用in 和exists 差異不大。數據庫

若是兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:oracle

例如:函數

表A(小表),表B(大表)1:oop

select * from A where cc in (select cc from B)效率低,用到了A 表上cc 列的索引;post

select * from A where exists(select cc from B where cc=A.cc)效率高,用到了B 表上cc 列的索引。性能

 

2.not in 和not exists大數據

若是查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;優化

而not extsts 的子查詢依然能用到表上的索引。因此不管那個表大,用not exists 都比not in 要快。spa

 

3.is null 和is not null的比較

索引列是不容許有null值的,也就是說若是某列存在空值,即便對該列建索引也不會提升性能。推薦方案:用其它相同功能的操做運算代替,如:a is not null 改成 a>0 或a>’ ’等。不容許字段爲空,而用一個缺省值代替空值,如申請中狀態字段不容許爲空,缺省爲申請。

 

4.LIKE操做符 

用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,這種查詢不會引用索引,若是改爲YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,性能確定大大提升。

 

5.union操做符

union在進行表連接後會篩選掉重複的記錄,因此在表連接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄:最多見的是過程表與歷史表UNION。如:

select * from gc_dfys 
union 
select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,若是表數據量大的話可能會致使用磁盤進行排序。
推薦方案:採用UNION ALL操做符替代UNION,由於UNION ALL操做只是簡單的將兩個結果合併後就返回。
 
6.聯接列,對於有聯接的列,即便最後的聯接值爲一個靜態值,優化器是不會使用索引的。咱們一塊兒來看一個例子,假定有一個職工表(employee),對於一個職工的姓和名分紅兩列存放(FIRST_NAME和LAST_NAME),如今要查詢一個叫比爾.克林頓(Bill Cliton)的職工。
select * from employss where first_name|| '' ||last_name = 'Beill Cliton' ;這樣的話系統優化器對基於last_name建立的索引沒有使用。
 
7.order by
ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什麼特別的限制,也能夠將函數加入列中(象聯接或者附加等)。任何在Order by語句的非索引項或者有計算表達式都將下降查詢速度。仔細檢查order by語句以找出非索引項或者表達式,它們會下降性能。解決這個問題的辦法就是重寫order by語句以使用索引,也能夠爲所使用的列創建另一個索引,同時應絕對避免在order by子句中使用表達式。
 
8.where子句後的條件順序對大數據量表查詢產生直接影響
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(銷戶標誌)兩個字段都沒進行索引,因此執行的時候都是全表掃描,第一條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佔用率明顯比第一條低。
 
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
條件內包括了多個本表的字段運算時不能進行索引,如:
ys_df>cx_df,沒法進行優化 
qc_bh || kh_bh=’5400250000’,優化處理:qc_bh=’5400’ and kh_bh=’250000’
 
10.ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最早處理,在FROM子句中包含多個表的狀況下,你必須選擇記錄條數最少的表做爲基礎表。若是有3個以上的錶鏈接查詢, 那就須要選擇交叉表(intersection table)做爲基礎表, 交叉表是指那個被其餘表所引用的表
 
11. WHERE子句中的鏈接順序:

ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的鏈接必須寫在其餘WHERE條件以前, 那些能夠過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.

12. SELECT子句中避免使用 ‘ * ‘:ORACLE在解析的過程當中, 會將’*’ 依次轉換成全部的列名, 這個工做是經過查詢數據字典完成的, 這意味着將耗費更多的時間。

13.減小訪問數據庫的次數:ORACLE在內部執行了許多工做: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數據塊等。

14.在SQL*Plus , SQL*Forms和Pro*C中從新設置ARRAYSIZE參數, 能夠增長每次數據庫訪問的檢索數據量 ,建議值爲200。

15. 整合簡單,無關聯的數據庫訪問:若是你有幾個簡單的數據庫查詢語句,你能夠把它們整合到一個查詢中(即便它們之間沒有關係) 。

16. 刪除重複記錄:最高效的刪除重複記錄方法 ( 由於使用了ROWID)例子:DELETE  FROM  EMP E  WHERE  E.ROWID > (SELECT MIN(X.ROWID) FROM  EMP X  WHERE  X.EMP_NO = E.EMP_NO)。

17. 用TRUNCATE替代DELETE:

18. 儘可能多使用COMMIT

COMMIT所釋放的資源:

a. 回滾段上用於恢復數據的信息.

b. 被程序語句得到的鎖

c. redo log buffer 中的空間

19.用where替換having子句,避免使用HAVING子句, HAVING 只會在檢索出全部記錄以後纔對結果集進行過濾. 這個處理須要排序,總計等操做.若是能經過WHERE子句限制記錄的數目,那就能減小這方面的開銷. (非oracle中)on、where、having這三個均可以加條件的子句中,on是最早執行where次之,having最後.由於on是先把不符合條件的記錄過濾後才進行統計,它就能夠減小中間運算要處理的數據,按理說應該速度是最快的,where也應該比having快點的,由於它過濾數據後才進行sum,在兩個表聯接時才用on的,因此在一個表的時候,就剩下where跟having比較了.在這單表查詢統計的狀況下,若是要過濾的條件沒有涉及到要計算字段,那它們的結果是同樣的,只是where可使用rushmore技術,而having就不能,在速度上後者要慢若是要涉及到計算的字 段,就表示在沒計算以前,這個字段的值是不肯定的,根據上篇寫的工做流程,where的做用時間是在計算以前就完成的,而having就是在計算後才起做 用的,因此在這種狀況下,二者的結果會不一樣。在多表聯接查詢時,on比where更早起做用。系統首先根據各個表之間的聯接條件,把多個表合成一個臨時表 後,再由where進行過濾,而後再計算,計算完後再由having進行過濾。因而可知,要想過濾條件起到正確的做用,首先要明白這個條件應該在何時起做用,而後再決定放在那裏。

20.使用表的別名(Alias)當在SQL語句中鏈接多個表時, 請使用表的別名並把別名前綴於每一個Column上.這樣一來,就能夠減小解析的時間並減小那些由Column歧義引發的語法錯誤。

21. 用索引提升效率:

22.用>=替代>
23. 用UNION替換OR (適用於索引列)
24.用where代替order by
低效: (索引不被使用) 
SELECT DEPT_CODE FROM  DEPT  ORDER BY  DEPT_TYPE 
高效: (使用索引) 
SELECT DEPT_CODE  FROM  DEPT  WHERE  DEPT_TYPE > 0
25.優化GROUP BY提升GROUP BY 語句的效率, 能夠經過將不須要的記錄在GROUP BY 以前過濾掉.下面兩個查詢返回相同結果但第二個明顯就快了許多.
低效: 
SELECT JOB , AVG (SAL) 
FROM EMP 
GROUP by JOB 
HAVING JOB = ‘PRESIDENT
OR JOB = ‘MANAGER' 
高效: 
SELECT JOB , AVG (SAL) 
FROM EMP 
WHERE JOB = ‘PRESIDENT
OR JOB = ‘MANAGER' 
GROUP by JOB
相關文章
相關標籤/搜索