itpub论坛回复: 直接赋值与select from dual的效率对比

问题: (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

请使用浏览器的分享功能分享到微信等