问题: (MountLion )
直接赋值与select from dual的效率对比
在pl/sql中,可以直接给变量赋值,也可以使用select ... into var from dual,这两种方式效率有差别吗?
开始我认为,select 要慢些,因为需要扫描dual表,虽然表很小,但也有消耗。然而实验结果让我大跌眼镜:
declare
a varchar2(30);
begin
for i in 1..100000 loop
select user into a from dual;
end loop;
end;
declare
a varchar2(30);
begin
for i in 1..100000 loop
a:=user;
end loop;
end;
select from dual 居然比直接赋值快10%左右,经过翻来覆去的实验,结果还是这样。
哪位可以解释一下原因?
我的回答:
user是个sql函数, 所以
a:=user;
实际上相当于
select user into b from dual;
a := b;
如果把user换成一个字符串常量, 那么可以看到第二个查询明显快。
从dbms_profiler验证:
declare
a varchar2(30);
begin
for i in 1..100000 loop
a:=user;
end loop;
end;
Unit Line Occurrences Text
ANONYMOUS BLOCK 1 2
ANONYMOUS BLOCK 4 100001
ANONYMOUS BLOCK 5 200000
这里的第5行(即a:=user;)执行了200000次,很是奇怪。 虽说我认为是相当于select user into b from dual;a := b; 但如果用select user into b from dual;a := b;代替a:=user; 并不会出现200000次的效果. 这个需要以后再仔细研究。
declare
a varchar2(30);
begin
for i in 1..100000 loop
select user into a from dual;
end loop;
end;
Unit Line Occurrences Text
ANONYMOUS BLOCK 1 2
ANONYMOUS BLOCK 4 100001
ANONYMOUS BLOCK 5 100000
再从sqltrace进行验证:
declare
a varchar2(30);
begin
for i in 1..100000 loop
a:=user;
end loop;
end;
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 4.23 4.47 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 4.23 4.47 0 0 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 59
********************************************************************************
SELECT user
from
sys.dual
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 0 0.00 0.00 0 0 0 0
Execute 100000 1.27 1.05 0 0 0 0
Fetch 100000 1.37 1.35 0 300000 0 100000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 200000 2.64 2.40 0 300000 0 100000