在查询中,绑定变量是⼀个占位符。例如,为了检索员⼯123的记录,可以查询:
select * p where empno = 123;
另外,也可以查询:
select * p where empno = :empno;
在典型系统中,查询员⼯123⼀次,可能再也不会查询。以后,将查询员⼯456,然后查询员⼯789等等。
如果在查询中使⽤⽂字(常量),那每次每个查询都是⼀个新查询,即在数据库中以前没有过的查询。每次查询必需经过分析、限定(名称解析)、
安全检查、优化等等,简单的说,执⾏的每条语句在每次执⾏时都将必需经过编译。
第⼆个查询使⽤了绑定变量:empno,它的值在查询执⾏时提供。查询经过⼀次编译后,考试⼤提⽰查询⽅案存储在共享池(库⾼速缓存)中,可以⽤来检索和重⽤。
在性能的差异是巨⼤的。
---
如果使⽤绑定变量,提交引⽤相同对象的完全相同的查询的⼈将使⽤共享池中的编译⽅案。只需编译⼦例程⼀次,就可以重复使⽤。
不仅使⽤较少的资源,⽽且可以减少锁存时间,降低锁存频率。这会他提⾼性能,并⼤⼤地提⾼可伸缩性。
--测试(根据机器不同⽽不同哦,本测试同⼀机器)
--使⽤了绑定变量的
declare
type rc is ref cursor;
l_rc rc;
l_dummy all_objects.object_name%type;
l_start number default sys._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._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._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._time - l_start)/100,2)||'秒');
end;
-------------------------------
--结果输出为22.42秒
-------------------------------
查询通常只是因为改变where⼦句中的内容⽽产⽣不同的结果。为了在这种情况下避免硬解析,需要使⽤绑定变量(bind variable)。它是⽤户放⼊查询中的占位符,它会告诉Oracle"我会随后为这个变量提供⼀个值,现在需要⽣成⼀个⽅案,但我实际执⾏语句的时候,我会为您提供应该使⽤的实际值"。
select * from emp where ename='KING'; //不使⽤绑定变量
select * from emp where ename=:bv //使⽤绑定变量
⼀般在 procedure or function 中使⽤,可以优化共享池的使⽤。
例⼦:
SQL> set serveroutput on
SQL> drop table hxz_12 ;
表已丢弃。
SQL> create table hxz_12(c number);
表已创建。
SQL> --考试⼤提⽰未绑定变量
SQL> declare
2 l_start number default _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((_time - l_start) / 100, 2) ||
9 ' ');
10 commit;
11 end;
12 /
2.
PL/SQL 过程已成功完成。
SQL> declare
2 l_start number default _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((_time - l_start) / 100, 2) ||
10 ' ');
11 commit;
12 end;
13 /
.
PL/SQL 过程已成功完成。
SQL>
Examda提⽰可见进⾏了变量绑定执⾏起来效果⽐没有进⾏变量绑定的要好很多。
发布评论