SQLServer(綁定變量的分析理解)

字號:

綁定變量
    在查詢中,綁定變量是一個占位符。例如,為了檢索員工123的記錄,可以查詢:
    select * from scott.emp where empno = 123;
    另外,也可以查詢:
    select * from scott.emp where empno = :empno;
    在典型系統(tǒng)中,查詢員工123一次,可能再也不會查詢。以后,將查詢員工456,然后查詢員工789等等。
    如果在查詢中使用文字(常量),那每次每個查詢都是一個新查詢,即在數(shù)據(jù)庫中以前沒有過的查詢。每次查詢必需經(jīng)過分析、限定(名稱解析)、
    安全檢查、優(yōu)化等等,簡單的說,執(zhí)行的每條語句在每次執(zhí)行時都將必需經(jīng)過編譯。
    第二個查詢使用了綁定變量:empno,它的值在查詢執(zhí)行時提供。查詢經(jīng)過一次編譯后,考試大提示查詢方案存儲在共享池(庫高速緩存)中,可以用來檢索和重用。
    在性能的差異是巨大的。
    ---
    如果使用綁定變量,提交引用相同對象的完全相同的查詢的人將使用共享池中的編譯方案。只需編譯子例程一次,就可以重復使用。
    不僅使用較少的資源,而且可以減少鎖存時間,降低鎖存頻率。這會他提高性能,并大大地提高可伸縮性。
    --測試(根據(jù)機器不同而不同哦,本測試同一機器)
    --使用了綁定變量的
    declare
    type rc is ref cursor;
    l_rc rc;
    l_dummy all_objects.object_name%type;
    l_start number default sys.dbms_utility.get_time;
    begin
    for i in 1..1000 loop
    open l_rc for
    'select a.object_name from all_objects a where a.object_id = :X' using i;
    fetch l_rc into l_dummy;
    close l_rc;
    end loop;
    dbms_output.put_line(round((sys.dbms_utility.get_time - l_start)/100,2)||'秒');
    end;
    -------------------------------
    --結果輸出為0.91秒
    -------------------------------
    --沒有綁定
    declare
    type rc is ref cursor;
    l_rc rc;
    l_dummy all_objects.object_name%type;
    l_start number default sys.dbms_utility.get_time;
    begin
    for i in 1..1000 loop
    open l_rc for
    'select a.object_name from all_objects a where a.object_id = ' ||i;
    fetch l_rc into l_dummy;
    close l_rc;
    end loop;
    dbms_output.put_line(round((sys.dbms_utility.get_time - l_start)/100,2)||'秒');
    end;
    -------------------------------
    --結果輸出為22.42秒
    -------------------------------
    查詢通常只是因為改變where子句中的內(nèi)容而產(chǎn)生不同的結果。為了在這種情況下避免硬解析,需要使用綁定變量(bind variable)。它是用戶放入查詢中的占位符,它會告訴Oracle"我會隨后為這個變量提供一個值,現(xiàn)在需要生成一個方案,但我實際執(zhí)行語句的時候,我會為您提供應該使用的實際值"。
    select * from emp where ename='KING'; //不使用綁定變量
    select * from emp where ename=:bv //使用綁定變量
    一般在 procedure or function 中使用,可以優(yōu)化共享池的使用。
    例子:
    SQL> set serveroutput on
    SQL> drop table hxz_12 ;
    表已丟棄。
    SQL> create table hxz_12(c number);
    表已創(chuàng)建。
    SQL> --考試大提示未綁定變量
    SQL> declare
    2 l_start number default dbms_utility.get_time;
    3 l_tabname varchar2(10) default 'hxz_12';
    4 begin
    5 for x in 1 .. 10000 loop
    6 Execute immediate 'insert into '||l_tabname||'(c) values (' || x || ')';
    7 end loop;
    8 dbms_output.put_line(round((dbms_utility.get_time - l_start) / 100, 2) ||
    9 ' seconds...');
    10 commit;
    11 end;
    12 /
    2.89 seconds...
    PL/SQL 過程已成功完成。
    SQL> declare
    2 l_start number default dbms_utility.get_time;
    3 l_tabname varchar2(10) default 'hxz_12';
    4 begin
    5 for x in 1 .. 10000 loop
    6 Execute immediate 'insert into '||l_tabname||'(c) values (:v)'
    7 using x;
    8 end loop;
    9 dbms_output.put_line(round((dbms_utility.get_time - l_start) / 100, 2) ||
    10 ' seconds...');
    11 commit;
    12 end;
    13 /
    .74 seconds...
    PL/SQL 過程已成功完成。
    SQL>
    Examda提示可見進行了變量綁定執(zhí)行起來效果比沒有進行變量綁定的要好很多。