SQL和PL/SQL的效能優化之六---使用和調優PL/SQL
1、PL/SQL的效能優勢
A、過程化的方法:SQL是非過程化語言,而PL/SQL是過程化語言,可操作優化器讀取等;
B、減少網路開銷:在客戶端-伺服器環境中,減少網路傳輸可以顯著地提高效能;
C、分解並攻克海量SQL語句:SQL語句越很雜越難以優化,可以用PL/SQL分解,單獨優化。
2、衡量PL/SQL的效能
A、下面的查詢列出了SQL語句,它包含PL/SQL的執行時間,PL/SQL佔總的SQL執行時間的比例和語句佔資料庫中所有PL/SQL開銷的比例:
select sql_id, substr(sql_text,1,500) as sql_text,
round(relapsed_time/1000) as elapsed_ms,
round(plsql_exec_time/1000) plsql_ms,
round(plsql_exec_time*100/elapsed_time,2) pct_plsql,
round(plsql_exec_time*100/sum(plsql_exec_time) over(), 2) pct_total_plsql
from v$sql
where plsql_exec_time > 0 and elapsed_time >0
order by plsql_exec_time desc;
B、PL/SQL剖析器,DBMS_PROFILER找出程式碼中最耗資源的行
例:我們要分析NOCOPY_TEST包中的一個程式:
DECLARE
returncode binary_integer;
begin
returncode := dbms_profiler.start_profiler('Profiler Demo 2'),
nocopy_test.test_copy(400,1);
returncode := dbms_profiler.stop_profiler;
dbms_output.put_line('Profiler.returncode = '||returncode);
commit;
end;
C、11G的分層剖析器
3、資料訪問優化--動態SQL和繫結變數的運用
4、程式碼優化
10G開始PLSQL_OPTIMIZE_LEVEL引數控制ORACLE可應用於PL/SQL程式的自動優化行為。有時,這些優化等價於重寫PL/SQL程式碼。
這個引數可以取如下值:
0--不優化;
1--較少的優化,沒有太大的調整;
2--(預設)明顯的調整,包括迴圈優化和自動BULK COLLECT;
3--(僅用於11G)更進一步優化,包括自動內聯子程式。
A、避免不必要的迴圈迭代;只要工作完成就立即使用EXIT語包退出迴圈。
B、將可能性最小的條件放在AND表示式的左邊,如果它是錯誤的,ORACLE就沒有必要計算第二個表示式的值;
例:IF t_amount(i) > i and t_time < '01-jun-98' then ... end if;
因為幾乎所有金額都大於1,但僅有很少的發生在1988年6月之前,如果上面表示式反轉,可以減少PL/SQL大約1/3的執行時間。
C、將可能性最大的條件放在OR表示式的左邊,如果它是正確的,ORACLE就沒有必要計算第二個表示式的值
D、將IF或CASE語句中的條件按可能性最大到最小的順序排列,可以減少需要的次數以幫助獲得性能提升。
E、避免深度地遞迴方法,迭代方法通常總是比遞迴效能更好,而且使用記憶體高效得多。
F、當給函式或過程傳遞很大的PL/SQL表作為引數時,考慮使用NOCOPY子句
p_input_table in out nocopy number_tab_type;
5、其它優化
5.1 內聯PL/SQL---是一種被很多優化編譯器用來提升程式碼效能的技術。內聯從子程式中抽取程式碼然後插入,內聯到呼叫程式碼中
可以用 pragma inline(函式,'YES')實現內聯或引數PLSQL_OPTMIZE_LEVEL設為3自動內聯
5.2 資料型別---PLS_INTEGER和SIMPLE_INTEGER比NUMBER運算更快。當合適的時候使用PLS_INTEGER和SIMPLE_INTEGER優化PL/SQL的整數計算。
5.3 當進行大量數字計算時,JAVA儲存過程的效能比直接使用PL/SQL要優化很多。而當使用高效的資料型別和本地編譯時,該優勢會減弱。
5.4 DML觸發器的效能
Create or replace trigger sales_apd
before update of amount_sold or insert
on sales
for each row
when (new.amount_sold> 1500)
declare
....
利用create trigger語句的of過去和when子句,以確保觸發器僅在必要時觸發。