pl/sql優化小知識點

1.選擇最有效的表名順序

oracle的解析器按照從右到左的順序處理from子句中的表名,因此寫在from子句最後的表(基礎表,drivingtable)將被最先處理。在from子句中包含多個表的情況下,你必須選擇記錄條數最少的表作爲基礎表。

2.where子句中的連接順序

oracle採用自下而上的順序解析where子句,根據這個原理,表之間的連接必須寫在其他where條件之前。

3.select子句中避免使用“*”

當你想在select子句中列出所有column時,使用動態sql列引用‘*’是一個方便的方法。不幸的是,這是一個非常低效的方法。實際上,oracle在解析的過程中,會將‘*’依次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味着將耗費更多的時間。

4.用exists代替in

實際情況看,使用exists代替in效果不是很明顯,基本一樣。
在許多基於基礎表的查詢中,爲了滿足一個條件,往往需要對另一個表進行連接。在這種情況下,使用exists或(no exists)通常將提高查詢的效率。

5.用表連接替換exists

在子查詢的表和主表查詢是多對一的情況,一般採用表連接的方式比exists更有效率。

6.用exists替換distinct

當提交一個包含一對多表信息的查詢時,避免在select子句中使用distinct,一般可以考慮用exists替換。
exists使查詢更爲迅速,因爲RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果。因此如果不是特別研究和追求速度的話,查詢一個表的數據需要關聯其他表的這種情況查詢,建議採用exists方式。

7.避免循環(遊標)裏面嵌查詢

遊標裏面不能嵌入查詢(或嵌入遊標),其實也不能有update或delete語句,只能有insert語句。但在實際的編程情況下是不可能完全避免的,但我們一定要儘量避免。該類問題也是程序中出現過的問題,該類問題也可以大大提升程序效率,請大家一定注意。
優化的方法是儘量把遊標循環中的查詢語句放到遊標查詢中一起查詢出來,這樣相當於只訪問了一次磁盤讀到內存;如果放到遊標中的話,假如遊標有100萬數據量,那麼程序需要100萬次磁盤,可以想象浪費了多少I/O的訪問。
如果在程序編寫上沒有辦法避免遊標中有查詢語句的話(一般情況是可以避免的),那麼也要保證遊標中的查詢使用索引(即查詢速度非常快),例如遊標100萬數據量,遊標中的查詢語句0.02秒,從這個速度來說是很快的,但總體上看100萬*0.02秒=5小時33分鐘,如果寫一個不夠優化的語句1秒,需要多次時間完成?

8.儘量使用union all 替換union

union會去掉重複的記錄,會有排序的動作,會浪費時間。因此在沒有重複記錄的情況下或允許有重複記錄的情況,要儘量採用union all來關聯。

9.使用decode函數來減少處理時間

使用decode函數可以避免重複掃描相同記錄或重複連接相同的表。

10.group by優化

group by 需要查詢後排序,進度慢影響性能,如果查詢數據量大,並且分組複雜,這樣的查詢語句在性能上是有問題的。

11.儘量避免使用order by 

order by需要查詢後排序,速度慢影響性能,如果查詢數據量大,排序的時間就很長。但我們也不能避免不使用,這樣大家一定注意的一點是如果使用order by,那麼排序的列表必須符合索引,這樣在速度上會得到很大的提升。

12.用where子句替換having子句

避免使用having子句,having只會在檢索所有記錄之後纔對結果集進行過濾。這個處理需要排序,總計等操作。如果能通過where子句限制記錄的數目,那就能減少這方面的開銷。

13.使用表別名

當在sql語句中連接多個表時,請使用表的別名並把別名前綴與每個column上。這樣一來,就可以減少解析的時間並減少那些由column歧義引起的語法錯誤。

14.刪除重複記錄

一般數據轉換的程序經常會用到該方法
最高效的刪除重複記錄的方法(因爲使用了ROWID)
delete from ac01 a 
where a.rowid>(select min(b.rowid) from ac01 b where a.aac002=b.aac002 and a.aac003=b.aac003);

15.COMMIT使用

數據轉換的程序需要注意這一點。
1.commit執行也是有時間的,不過時間特別短,但提交頻率特別大必然也會浪費時間;
2.commit可以釋放資源,在大量數據更新時,必須及時提交。
如果一條一提交,需要提交5000萬必然浪費時間;如果整體提交,資源不能釋放,性能必然下降。在實際編程時,應注意提交的次數和提交的數據量之間的平衡關係。

16.減少多表關聯

表關聯的越多,查詢速度就越慢,儘量減少多個表的關聯,建議表關聯不要超過3個(子查詢也屬於表關聯)。
數據轉換上會存在大數據量表的關聯,關聯多了會影響索引的效率,可以採用建立臨時表的方法,有時更能提高速度。

17.批量數據插入

數據轉換時或大業務數據插入時,有以下幾種辦法進行數據插入(不包括imp,impdp和sqlloader)
1.Insert into ...select 方式
將查詢的結果一次插入到目標表中
例如:insert into ac02 select * from ac01;
由於是一次查詢一次插入,並且最後一次提交,它的速度要比下面描述的cursor的速度要快。但查詢插入的數據量過大必然會佔用更多的內存和undo表空間,只能在插入完成後提交,這樣資源不能釋放,會導致回滾表空間不足和快照過久的問題,另外一旦失敗需要全部回滾。因此建議小數據量(例如:300萬以下)的導入採用該種方式。
2.cursor方式
定義遊標,然後逐行進行插入,然後定量提交。
3.批綁定的方式
通過遊標查詢將數據逐行寫到數組裏(實際上就是內存),然後通過批綁定的語句forall...insert into ..select ..into  values..,將內存的數據一次寫到數據文件中。相比cursor的方式減少了對I/O的訪問次數,提高了速度,但注意內存別溢出了。

18.索引使用優化

在實際的應用系統中索引問題導致性能問題可能佔到百分之八十,在程序優化上索引問題是需要我們特別關注的。本段主要描述什麼情況索引不生效。
1.避免在索引列上使用函數或運算
這個問題是在我們實際編程中出現過的,請大家一定注意。在索引列上使用函數或運算,查詢條件都不會使用索引。
例如:
不使用索引
select * from ac01 where ka060='10001000' and to_char(aae030,'yyyymm')='200801';

使用索引
select * from ac01 where ka060='10001000' and aae030=to_date('200801','yyyymm');

不使用索引
select * from ac01 where ka060='10001000' and aae030+1=sysdate;

使用索引
select * from ac01 where ka060='10001000' and aae030=sysdate-1;

2.避免改變索引列的類型
索引列的條件如果類型不匹配,則不能使用索引
例如:
不使用索引
select * from ac01 where ka060=10001000;

使用索引
select * from ac01 where ka060='10001000';

3.避免在索引列上使用NOT
避免在索引列上使用NOT,NOT不會使查詢條件使用索引。對於!=這樣的判斷也是不能使用索引的,索引只能告訴你什麼存在於表中,而不能告訴你什麼不存在於表中。
例如:
不使用索引(低效)
select * from ac01 where not ka060='10';

使用索引(高效)
select * from ac01 where ka060 in('20','30');

19.用>=替代>

雖然效果不是特別明顯,但是建議採用這種方式
低效:
select * from ac01 where ka060>'10';

高效:
select * from ac01 where ka060>='20';
兩者的區別在於,前者DBMS首先定位到ka060=‘10’的記錄並且向前掃描到第一個ka060大於10的記錄;而後者DBMS將直接跳到ka060='20'的記錄。

20.避免在索引列上使用is null 和is not null

對於索引列使用is null或is not null不會使用該索引,因爲空值不存在於索引列中,所以where子句中對索引列進行空值比較將oracle停用該索引。
例如:
低效(索引失效)
select * from ac01 where ka060 is not null;

高效(索引有效)
select * from ac01 where ka060 in('10','20','30');
在實際開發中,這樣的問題很難避免,如果不是特別影響速度或要求速度的,可以忽略。

21.帶通配符(%)的like語句

%在常量前面索引就不會使用

22.總是使用索引的第一個列

如果索引是建立在多個列上,只有在它的第一個列被where子句引用時,優化器纔會選擇使用該索引。
例如:
ac01的複合索引:ac011,ac012,ac013
select * from ac01 where ac012='01' and ac013='03';不會使用索引
select * from ac01 where ac011='01';使用索引
如果不使用索引第一列基本上不會使用索引,使用索引要按照索引的順序使用,另外使用複合索引的列越多,查詢的速度就越快。

 23.多個平等的索引

當sql語句的執行路徑可以使用分佈在多個表上的多個索引時,oracle會同時使用多個索引並在運行時對它們的記錄進行合併,檢索出僅對全部索引有效的記錄。
在oracle選擇執行路徑時,唯一性索引的等級高於非唯一性索引,然而這個規則只有當where子句中索引列和常量比較纔有效。如果索引列和其他表中的索引列相比較,這種子句在優化器中的等級是非常低的。
如果不同表中相同等級的索引被引用,from 子句中表的順序將決定哪個會被率先使用。from子句中最後的表的索引將有最高的優先級。
如果同一個表中擁有相同等級的索引,oracle會分析最有效的索引去引用,其他的索引不會使用,如果這些相同等級的索引效果差不多,oracle可能會自動合併使用。

24.不明確的索引等級

當oracle無法判斷索引的等級高低差別,優化器將只使用一個索引它就是where子句中列在最前面的。

25.自動選擇索引

如果表中有兩個及以上的索引,其中有一個是唯一性索引,其他是非唯一性。
在這種情況下,oracle將使用唯一性索引而完全忽略非唯一性索引。

26.一般導致系統性能慢的因素

1.硬件:客戶端、服務器cpu、內存和存儲設備配置不符合應用系統要求。
2.網絡:網速低,丟包
3.操作系統參數配置:參數設置不合理
4.受到其他軟件干擾:例如防火牆、病毒等。
5.weblogic設置:參數設置不合理
6.oracle設置:內存、表空間、redolog、系統參數設置不合理
PLSQL程序:plsql不優化、未使用索引、鎖表
在不同現象下,可能導致性能問題的因素:
1.一般來說,如果在不辦理業務的情況下,整個系統性能就慢的話,應該和PLSQL程序優化是沒有關係的。可能的因素爲硬件、網絡、操作系統、其他軟甲干擾、oracle設置。
2.只有在業務繁忙的時候,整個系統性能慢,有可能的因素爲硬件、操作系統設置、weblogic設置、oracle設置、PLSQL程序、如果sqlplus做查詢都慢,那麼就和weblogic沒有關係。
3.一般來說,如果不辦理業務的情況下,個別業務模塊就慢,那麼基本上就是PLSQL程序不優化或未使用索引造成的。
4.只有在業務繁忙的時候,個別業務模塊慢,有可能的因素有硬件、操作系統設置、weblogic設置、oracle設置、plsql程序、鎖表。
這裏我們重點說明PLSQL優化、索引優化。
PLSQL優化、索引不使用的問題產生的影響:
1.對於某段不優化的程序或語句頻繁或者全表掃描一個表時,它訪問磁盤的時間和佔用的吞吐量是很大的,這就導致系統I/O長時間處於忙碌狀態,導致整個系統性能下降。
2.對於某段不優化的程序或語句頻繁或者全表掃描一個表時,其他的業務程序也訪問同一個表時,速度將大大下降。
3.如果是更新表時間較長,還可能會導致鎖等待,導致會話堵塞,weblogic端也出現壓力問題,導致整個系統性能下降。
我們一般根據這些現象、以及一些方法判斷,來初步分析產生性能問題的大致原因的範圍。不過對於這一點,還是比較困難的,因爲產生問題的原因是多種的,並且還有一定的關聯。下面的章節介紹我們一定斷定是PLSQL優化、不使用索引的問題,我們通過什麼方法具體定位問題。
1.Expain plan分析索引使用
在PLSQLdeveloper等工具有一個Expain plan分析的功能,這個功能可以幫助我們分析sql語句是否使用了索引、使用哪些索引和使用索引的效果。
1.1選擇expain plan窗口
1.2在上面欄中輸入sql語句然後點擊工具欄中的execute執行,就會在下面顯示
optmizergoal優化器的默認方式(也可手工選擇),以及下面的解釋計劃,從解釋計劃上可以看到哪個條件語句使用了索引,哪個沒用,哪個表使用了索引,使用了哪個索引,哪些表是全表掃描的
1.3分析內容說明
cost:根據優化程序的基於開銷的方法所估計出的操作開銷值,對於使用基於規則方法的語句該列爲空,該列值沒有特定的測量單位,它只是一個用於比較執行計劃開銷大小的權重值
cardinality:根據基於開銷的方法對操作所訪問的行數的估計值
bytes:根據基於開銷的方法對操作所訪問字節的估計
通過設置,我們還可以看見更多的信息,如CPU使用、時間等等。
全表掃描的肯定是速度慢的,如果是大數據量的表,那麼這個語句是絕對影響性能的。
另外使用了索引也不一定性能就高,因爲索引使用也有效率高低的情況,下面列出索引常見的使用類型
1.index unique scan唯一索引掃描,速度最快
2.index range scan範圍索引掃描,使用這個索引時,就需要看cost、cardinality,bytes的大小了,如果特別大,有時候還可能低於全表掃描的速度。
我們在知道語句有問題,或者我們隊語句進行優化時,這個工具是非常有用的。
2.topsql分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章