動態SQL、綁定變量、靜態SQL的性能對比

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專家高級編程>

相關文章
相關標籤/搜索