在oracle中繫結變數的使用
阿新 • • 發佈:2019-02-18
不使用繫結變數而使用硬編碼是oracle效能問題的主要原因和可伸縮性的主要障礙
而且這種障礙是除了使用繫結變數以外很難改變的!
下面根據一個簡單的試驗來檢視硬編碼與使用繫結變數對效能的影響:
在一個查詢中我們可以使用兩種方式:
比如查詢個人編號:
select * from ac01 where aac001=123;
另外,也可以查詢:
select * from ac01 where aac001=:grbh;
在典型的系統中,查詢員工123 一次,可能以後也不會查詢,以後將查詢員工456,然後查詢員工789,等
對於這個查詢方式,我們看到,對於每一次的查詢來說都是新的查詢,即資料庫中沒有過的查詢。每次的查詢都要經過分析、限定(名稱解析)、安全檢查、優化等等,簡單的說,執行的每條語句在每次執行時都將必須經過編譯。這樣的結果會造成share pool,即SGA中的共享池迅速的填滿,而oracle不得不花費大量的時間來整理,這也違背了share pool的設計思想。
然而,第二個查詢使用了繫結變數:grbh。查詢經過一個編譯後,查詢方案儲存在共享池中,只保留這一個副本,可以用來檢索和重用。
在效能和可伸縮性方面,這兩者的差異是巨大的,甚至是驚人的。
看看這個例子:
SQL> alter system flush shared_pool
2 ;
System altered.
SQL> set timing on
SQL> declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id ='||i;
11 fetch l_rc into l_dummy;
12 close l_rc;
13 end loop;
14 dbms_output.put_line(round((dbms_utility.get_time-l_start)/100,2)||
15 'seconds ..');
16 end;
17 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:11.09
注意,沒有使用繫結變數方式,花費了11秒
SQL> declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id=:x'
11 using i;
12 fetch l_rc into l_dummy;
13 close l_rc;
14 end loop;
15 dums_output.put_line
16 (round((dbms_utility.get_time-l_start)/100,2)||
17 'seconds..');
18 end;
19 /
dums_output.put_line
*
ERROR at line 15:
ORA-06550: line 15, column 2:
PLS-00201: identifier 'DUMS_OUTPUT.PUT_LINE' must be declared
ORA-06550: line 15, column 2:
PL/SQL: Statement ignored
Elapsed: 00:00:00.08
SQL> edit
Wrote file afiedt.buf
1 declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id=:x'
11 using i;
12 fetch l_rc into l_dummy;
13 close l_rc;
14 end loop;
15 dbms_output.put_line
16 (round((dbms_utility.get_time-l_start)/100,2)||
17 'seconds..');
18* end;
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.18
而使用繫結變數的方式,只用了不到一秒的時間!
從而可以看出,對於繫結變數的使用,可以提高系統性能的極大提高![size=xx-large][/size]
而且這種障礙是除了使用繫結變數以外很難改變的!
下面根據一個簡單的試驗來檢視硬編碼與使用繫結變數對效能的影響:
在一個查詢中我們可以使用兩種方式:
比如查詢個人編號:
select * from ac01 where aac001=123;
另外,也可以查詢:
select * from ac01 where aac001=:grbh;
在典型的系統中,查詢員工123 一次,可能以後也不會查詢,以後將查詢員工456,然後查詢員工789,等
對於這個查詢方式,我們看到,對於每一次的查詢來說都是新的查詢,即資料庫中沒有過的查詢。每次的查詢都要經過分析、限定(名稱解析)、安全檢查、優化等等,簡單的說,執行的每條語句在每次執行時都將必須經過編譯。這樣的結果會造成share pool,即SGA中的共享池迅速的填滿,而oracle不得不花費大量的時間來整理,這也違背了share pool的設計思想。
然而,第二個查詢使用了繫結變數:grbh。查詢經過一個編譯後,查詢方案儲存在共享池中,只保留這一個副本,可以用來檢索和重用。
在效能和可伸縮性方面,這兩者的差異是巨大的,甚至是驚人的。
看看這個例子:
SQL> alter system flush shared_pool
2 ;
System altered.
SQL> set timing on
SQL> declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id ='||i;
11 fetch l_rc into l_dummy;
12 close l_rc;
13 end loop;
14 dbms_output.put_line(round((dbms_utility.get_time-l_start)/100,2)||
15 'seconds ..');
16 end;
17 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:11.09
注意,沒有使用繫結變數方式,花費了11秒
SQL> declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id=:x'
11 using i;
12 fetch l_rc into l_dummy;
13 close l_rc;
14 end loop;
15 dums_output.put_line
16 (round((dbms_utility.get_time-l_start)/100,2)||
17 'seconds..');
18 end;
19 /
dums_output.put_line
*
ERROR at line 15:
ORA-06550: line 15, column 2:
PLS-00201: identifier 'DUMS_OUTPUT.PUT_LINE' must be declared
ORA-06550: line 15, column 2:
PL/SQL: Statement ignored
Elapsed: 00:00:00.08
SQL> edit
Wrote file afiedt.buf
1 declare
2 type rc is ref cursor;
3 l_rc rc;
4 l_dummy all_objects.object_name%type;
5 l_start number default dbms_utility.get_time;
6 begin
7 for i in 1..1000
8 loop
9 open l_rc for
10 'select object_name from all_objects where object_id=:x'
11 using i;
12 fetch l_rc into l_dummy;
13 close l_rc;
14 end loop;
15 dbms_output.put_line
16 (round((dbms_utility.get_time-l_start)/100,2)||
17 'seconds..');
18* end;
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.18
而使用繫結變數的方式,只用了不到一秒的時間!
從而可以看出,對於繫結變數的使用,可以提高系統性能的極大提高![size=xx-large][/size]