Oracle 11g中的Native PL/SQL程式碼編譯
Oracle環境中,PL/SQL是我們進行業務邏輯實現的最佳手段,同時也是和Oracle資料庫本身結合的最好的語言。使用好PL/SQL本身功能,可以大幅度提高我們的工作效率。
我們從最開始學習計算機和程式設計開始,就接觸到一個概念叫做“二進位制程式碼”。計算機可以直接進行二進位制程式碼的執行,就目前而言,二進位制是計算機執行速度最快的一種形式。其他的高階語言,如C、C++,都是透過編譯Compile和連線Link過程,轉化為二進位制程式。
二進位制程式的特點是執行速度快。但是缺點也是明顯的,那就是針對一種物理機器型別(如CPU架構)、一種作業系統,二進位制執行程式的格式定義都是不同的。所以,針對每一種作業系統和物理平臺,理論上我們都需要進行一遍Compile和Link過程,形成獨特的可執行程式。
中立語言,或者稱為中間語言的出現,結束了這樣的局面。這種代表性就是Java和諸多的指令碼語言,藉助一個“平臺相關”的虛擬機器軟體,我們可以讓相同的程式碼在不同平臺上執行。這也就是所謂的“一次編譯,多處執行”。
預設情況下,PL/SQL程式碼就是這樣的中間語言,也可以稱為解釋語言。在不同的平臺上,相同的程式碼在執行。相對於Native程式碼而言,解析程式碼的效能一直是人們關注的重要問題。將程式碼Native本地化,是人們經常提到的一種程式最佳化手段。
1、PL/SQL語句Native化
PL/SQL語句的Native化,是從Oracle9i引入的。最開始進行native的初衷就是效能,通常native的PL/SQL程式碼要比解釋形式(interpreted form)執行速度快。早期的native化是比較費力氣的,需要我們提供出本地的編譯器地址。
PL/SQL語句的native過程需要我們安裝額外的C編譯器,這個在一些生產環境下,還是有安全方面的顧慮的。
在9i和10g時代,資料庫中包括一個引數名為plsql_native_library_dir,用於指定本地的編譯器目錄位置。在11g中,這個引數被取消,進行程式碼native的過程也變得比較簡單起來。
在11g中,Oracle是不需要伺服器上額外安裝C編譯器的。Oracle會直接將需要native化的PL/SQL程式碼轉化到伺服器上的shared library(DDL)。由此,進行PL/SQL的本地編譯就變得很簡單,只需要一個開關裝置。這個就是Oracle引數plsql_code_type。
在使用native PL/SQL的時候,我們一定注意使用記憶體物件的不同。Native PL/SQL程式碼對應的機器碼(machine code)在被調入資料庫catalog之前,是與PGA記憶體進行對映。而解釋程式碼(interpreted form code)則是和SGA進行對應。所以,在使用native code的時候,對SGA的消耗是減少的趨勢。
2、開關引數plsql_code_type
從Oracle 11g開始,我們可以使用plsql_code_type來控制編譯器選擇開關。我們選擇Oracle11g進行實驗。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 – Production
相關引數
SQL> show parameter plsql_code
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
plsql_code_type string INTERPRETED
預設情況下,Oracle是選擇解釋程式碼的形式進行編譯的。透過檢視user/all/dba_plsql_object_settings,我們是可以看到對應儲存程式碼物件使用的編譯形式的。
首先,我們使用預設方式進行儲存過程編譯。
SQL> create or replace procedure P_RECE_CALL_TEST is
2 i number;
3 c number;
4 begin
5 for i in 1..100 loop
6 select count(*) into c from emp;
7 dbms_output.put_line(to_char(c));
8 end loop;
9 end P_RECE_CALL_TEST;
10 /
Procedure created
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
P_RECE_CALL_TEST INTERPRETED
程式碼物件的plsql_code_type列顯示了物件的編譯形式。我們對於單獨的儲存過程,可以不透過引數修改,而是在compile過程中,直接指定編譯方式。這樣也是可以將程式碼編譯為native方式。
SQL> alter procedure p_rece_call_test compile plsql_code_type=native;
Procedure altered
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
P_RECE_CALL_TEST NATIVE
配置引數plsql_code_type比較簡單,目前版本Oracle支援Interpreted和Native兩個選項值。預設取值為Interpreted,表示將程式程式碼編譯為解析形式。另一個就是Native,表示編譯為原生程式碼。我們可以在session level進行靈活的配置。
SQL> alter session set plsql_code_type='native';
Session altered
SQL> alter procedure p_rece_call_test compile;
Procedure altered
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
P_RECE_CALL_TEST NATIVE
重新登入之後,可以將其編譯回解釋狀態。
SQL> conn scott/tiger@ora11g;
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.3.0
Connected as scott
SQL> alter procedure p_rece_call_test compile;
Procedure altered
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
P_RECE_CALL_TEST INTERPRETED
3、效能對比
PL/SQL本地化程式碼最大的好處和優勢就在於效能。特別是11g版本下,本地Native的優勢更加明顯。
我們選擇一個比較消耗資源的函式——斐波納妾數列計算第n項,採用遞迴的結構進行計算。
SQL> create or replace function fib(n number)
2 return number
3 is
4 begin
5 if (n<=2) then
6 return n;
7 else
8 return fib(n-1)+fib(n-2);
9 end if;
10 end;
11 /
Function created
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
FIB INTERPRETED
執行實驗前,清理shared_pool和buffer_cache。
SQL> alter system flush shared_pool;
System altered.
SQL> alter system flush buffer_cache;
System altered.
SQL> set timing on;
SQL> set serveroutput on;
SQL> declare
2 n number;
3 begin
4 n := fib(40);
5 dbms_output.put_line('Result is : '||n);
6 end;
7 /
Result is : 165580141
PL/SQL procedure successfully completed
Executed in 43.547 seconds
N=40時候,PL/SQL解釋形式程式碼執行時間43.55s計算出結果。下面我們看看Native化之後的情況。
SQL> alter function fib compile plsql_code_type=native;
Function altered
Executed in 0.219 seconds
SQL> select name, plsql_code_type from user_plsql_object_settings;
NAME PLSQL_CODE_TYPE
------------------------------ --------------------
FIB NATIVE
Executed in 0.078 seconds
第二次執行相同計算任務。
SQL> alter system flush shared_pool;
System altered.
SQL> alter system flush buffer_cache;
System altered.
SQL> set timing on;
SQL> set serveroutput on;
SQL> declare
2 n number;
3 begin
4 n := fib(40);
5 dbms_output.put_line('Result is : '||n);
6 end;
7 /
Result is : 165580141
PL/SQL procedure successfully completed
Executed in 25.734 seconds
第二次native執行情況,看出為25.73s完成計算。效能提升接近一半!
4、結論
我們在編寫pl/sql程式碼的時候,效能是一個非常重要的考量方式。Native程式化在一定程度上可以提高效率。不過應該看到,Native化程式是有條件的。Native PL/SQL節省的時間成本在PL/SQL引擎的層面,而SQL語句引擎方面不會有很大程度的提升。
所以,如果我們的程式碼中以流程、計算和迴圈判斷為主體,SQL語句相對較少,那麼使用Native化是比較“划算”的。反之,如果主要都是在進行SQL語句計算操作,即使我們將程式碼Native化,獲取到的優勢也比較少。
另一方面,Native化的程式在遷移、升級的時候,也許會有很多額外的問題和關注點。也是我們需要注意慎用的方面。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-777265/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle PL/SQL編寫PL/SQL程式碼的注意事項OracleSQL
- Oracle PL/SQL程式碼中的註釋OracleSQL
- 配置UltraEdit為Oracle PL/SQL程式碼編輯器OracleSQL
- Oracle 資料庫11g新特性之高效 PL/SQL 編碼Oracle資料庫SQL
- Oracle PL/SQL編譯警告PLSQL_WARNINGSOracleSQL編譯
- 從一個案例看PL/SQL程式碼片的編譯與執行SQL編譯
- 應遵循的PL/SQL編碼規則 - ORACLE (zt)SQLOracle
- PL/SQL 01 程式碼編寫規則SQL
- PL/SQL的編碼規則SQL
- Oracle 11g系列:SQL Plus與PL/SQLOracleSQL
- Oracle PL/SQL 優化與調整 – PL/SQL Native Compilation 說明OracleSQL優化
- pl/sql程式碼中不得犯的錯誤!SQL
- oracle PL/SQL中的過載OracleSQL
- 加密PL/SQL程式碼加密SQL
- 使用PL/Scope分析PL/SQL程式碼SQL
- Oracle PL/SQL中EXCEPTION用法OracleSQLException
- 【TUNE_ORACLE】列出LOOP套LOOP的PL/SQL程式碼SQL參考OracleOOPSQL
- 保護你的 PL/SQL 程式碼!SQL
- 【Oracle】--PL/SQL匯入Oracle sql指令碼"傻瓜教程"OracleSQL指令碼
- Oracle PL/SQLOracleSQL
- 將PL/SQL程式碼封裝在靈巧的包中SQL封裝
- Oracle 11g PL/SQL 使用者自定義 ExceptionOracleSQLException
- PLSQL Language Reference-PL/SQL語言基礎-條件編譯-獲取和列印編譯後的原始碼文字SQL編譯原始碼
- 關於pl/sql的程式碼保護SQL
- Oracle PL/SQL INDICESOracleSQL
- oracle PL/SQL示例OracleSQL
- 【SQL/PLUS】Oracle PL/SQL程式設計用set serveroutput onSQLOracle程式設計Server
- Oracle 12c中增強的PL/SQL功能OracleSQL
- oracle中取得儲存過程、函式等pl sql原始碼的方法Oracle儲存過程函式SQL原始碼
- 數棧產品中的程式碼編譯器編譯
- PLSQL Language Reference-PL/SQL語言基礎-條件編譯-條件編譯指令限制SQL編譯
- PLSQL Language Reference-PL/SQL語言基礎-條件編譯-條件編譯舉例SQL編譯
- pl/sql中的row物件SQL物件
- React Native 編譯命令React Native編譯
- 應遵循的PL/SQL編碼規則 (作者:Steven Feuerstein) ztSQL
- Oracle 的PL/SQL語言使用OracleSQL
- oracle pl/sql programmingOracleSQL
- ORACLE EBS系統中的編譯Oracle編譯