1 測試樣例 sql
下面的三個存儲過程,分別使用了動態SQL、綁定變量、靜態SQL三種編程方式。具體存儲過程內容以下: 編程
l 動態SQL oop
create or replace procedure proc1 as 測試
begin spa
for i in 1 .. 100000 loop 字符串
execute immediate 'insertinto t values (' || i || ')'; 虛擬機
commit; it
end loop; 編譯
end proc1; table
l 綁定變量
create or replace procedure proc2 as
begin
for i in 1 .. 100000 loop execute immediate 'insert into t values(:X)' using i; commit;
end loop;
end proc2;
l 靜態SQL
create or replace procedure proc3 as
begin
for i in 1 .. 100000 loop
insert into t values(i); commit;
end loop;
end proc3;
2 測試過程
測試過程的步驟爲
1) drop table t purge;
2) create table t (x int);
3) alter system flush shared_pool;
4) set timing on
5) exec procxxx;
6) select count(*) from t;
在上述的測試過程當中,因爲每次測試時的表全是新的,並刷新了共享池,因此每次的測試效果仍是比較正確的。這次測試是在物理機上進行的測試,而非虛擬機上進行測試。
3 測試結果3.1 動態SQL
Proc1存儲過程使用了動態SQL,這樣就會在每次執行insert語句時,要對每個insert語句進行硬解析,這樣就增長了共享池的硬解析開銷,下面是v$sql視圖中的結果
SQL_TEXT EXECUTIONS PARSE_CALLS
------------------------------------------------------------ -----------
BEGINproc1; END; 1 1
insertinto t values (99280) 1 1
insertinto t values (99310) 1 1
insertinto t values (99362) 1 1
insertinto t values (99377) 1 1
insertinto t values (99399) 1 1
insertinto t values (99474) 1 1
insertinto t values (99544) 1 1
insertinto t values (99592) 1 1
insertinto t values (99601) 1 1
insertinto t values (99634) 1 1
insertinto t values (99696) 1 1
insertinto t values (99746) 1 1
insertinto t values (99804) 1 1
insertinto t values (99807) 1 1
insertinto t values (99859) 1 1
insertinto t values (99861) 1 1
insertinto t values (99930) 1 1
insertinto t values (99936) 1 1
insertinto t values (99956) 1 1
proc1存儲過程,在本次測試中使用了24.25秒,具體結果以下
SQL> exec proc1;
PL/SQL procedure successfully completed.
Elapsed: 00:00:24.25
3.2 綁定變量
Proc2存儲過程使用了綁定變量,這樣在執行過程上,就會減小硬解析的開銷,下降共享池的爭用。在執行過程當中,v$sql視圖中的結果以下
SQL_TEXT EXECUTIONS PARSE_CALLS
------------------------------------------------------------ -----------
BEGIN proc2;END; 1 1
insert intot values (:X) 100000 0
insert語句並無解析1次執行1次,而是解析了1次,執行了10萬次。Proc2存儲過程,在本次測試中使用了20.94秒,執行結果以下
SQL>exec proc2;
PL/SQL proceduresuccessfully completed.
Elapsed:00:00:20.94
3.3 靜態SQL
Proc3存儲過程使用了靜態SQL,這樣在編譯過程當中insert語句就解析好了,而不像proc2存儲過程須要在執行過程當中再解析,這樣節省了一些時間,具體的測試結果以下
SQL_TEXT EXECUTIONS PARSE_CALLS
------------------------------------------------------------ -----------
BEGINproc3; END; 1 1
INSERTINTO T VALUES(:B1 ) 100000 0
在靜態SQL中,insert語句也是使用了綁定變量,因此也是解析1次,而後屢次執行。Proc3存儲過程執行了17.82秒,具體結果以下
SQL>exec proc3;
PL/SQL proceduresuccessfully completed.
Elapsed:00:00:17.82
4 測試總結
動態SQL適用於表名及查詢字段名未知的狀況。在已知查詢字段名及表名的狀況下,使用動態SQL(字符串拼接方式)會增長硬解析的開銷,在這種狀況下,建議使用靜態SQL,這樣能夠提升執行效率。在過程過程用拼湊的動態sql效率並不高,有時候還不如程序直接傳遞sql.靜態SQL是前置編譯綁定,動態SQL是後期執行時才編譯綁定
參考:
< Oracle專家高級編程>