Oracle 11g中的Native PL/SQL代碼編譯

Oracle環境中,PL/SQL是咱們進行業務邏輯實現的最佳手段,同時也是和Oracle數據庫自己結合的最好的語言。使用好PL/SQL自己功能,能夠大幅度提升咱們的工做效率。java

咱們從最開始學習計算機和編程開始,就接觸到一個概念叫作「二進制程序碼」。計算機能夠直接進行二進制代碼的執行,就目前而言,二進制是計算機執行速度最快的一種形式。其餘的高級語言,如C、C++,都是經過編譯Compile和鏈接Link過程,轉化爲二進制程序。linux

二進制程序的特色是執行速度快。可是缺點也是明顯的,那就是針對一種物理機器類型(如CPU架構)、一種操做系統,二進制執行程序的格式定義都是不一樣的。因此,針對每一種操做系統和物理平臺,理論上咱們都須要進行一遍Compile和Link過程,造成獨特的可執行程序。sql

中立語言,或者稱爲中間語言的出現,結束了這樣的局面。這種表明性就是Java和諸多的腳本語言,藉助一個「平臺相關」的虛擬機軟件,咱們可讓相同的代碼在不一樣平臺上運行。這也就是所謂的「一次編譯,多處執行」。數據庫

默認狀況下,PL/SQL代碼就是這樣的中間語言,也能夠稱爲解釋語言。在不一樣的平臺上,相同的代碼在運行。相對於Native代碼而言,解析代碼的性能一直是人們關注的重要問題。將代碼Native本地化,是人們常常提到的一種程序優化手段。編程

 

一、PL/SQL語句Native化安全

 

PL/SQL語句的Native化,是從Oracle9i引入的。最開始進行native的初衷就是性能,一般native的PL/SQL代碼要比解釋形式(interpreted form)執行速度快。早期的native化是比較費力氣的,須要咱們提供出本地的編譯器地址。服務器

PL/SQL語句的native過程須要咱們安裝額外的C編譯器,這個在一些生產環境下,仍是有安全方面的顧慮的。session

在9i和10g時代,數據庫中包括一個參數名爲plsql_native_library_dir,用於指定本地的編譯器目錄位置。在11g中,這個參數被取消,進行代碼native的過程也變得比較簡單起來。架構

在11g中,Oracle是不須要服務器上額外安裝C編譯器的。Oracle會直接將須要native化的PL/SQL代碼轉化到服務器上的shared library(DDL)。由此,進行PL/SQL的本地編譯就變得很簡單,只須要一個開關設備。這個就是Oracle參數plsql_code_type。oracle

在使用native PL/SQL的時候,咱們必定注意使用內存對象的不一樣。Native PL/SQL代碼對應的機器碼(machine code)在被調入數據庫catalog以前,是與PGA內存進行映射。而解釋代碼(interpreted form code)則是和SGA進行對應。因此,在使用native code的時候,對SGA的消耗是減小的趨勢。

 

二、開關參數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

 

 

三、性能對比

 

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完成計算。性能提高接近一半!

 

四、結論

 

咱們在編寫pl/sql代碼的時候,性能是一個很是重要的考量方式。Native程序化在必定程度上能夠提升效率。不過應該看到,Native化程序是有條件的。Native PL/SQL節省的時間成本在PL/SQL引擎的層面,而SQL語句引擎方面不會有很大程度的提高。

因此,若是咱們的代碼中以流程、計算和循環判斷爲主體,SQL語句相對較少,那麼使用Native化是比較「划算」的。反之,若是主要都是在進行SQL語句計算操做,即便咱們將代碼Native化,獲取到的優點也比較少。

另外一方面,Native化的程序在遷移、升級的時候,也許會有不少額外的問題和關注點。也是咱們須要注意慎用的方面。

相關文章
相關標籤/搜索