很长一段时间以来,我一直在使用EXISTS
子句来确定给定条件中给定表中是否至少存在一条记录。
例如 - 如果我想查看“employee”表中是否存在lastname ='smith'的员工,我使用了以下查询
select 1
into v_exists_flag
from dual
where exists (select 1
from employee
where lastname = 'smith'
)
这肯定比使用count(*)子句更有效。
select count(*)
into v_count
from employee
where lastname = 'smith'
如果v_count> 0然后......
但是,最近有人提到使用ROWNUM = 1比使用EXISTS子句有更好的性能,如下所示
select 1
into v_count
from employee
where lastname = 'smith'
and rownum = 1
这是对的吗?有人可以证实这一点。
提前致谢
答案 0 :(得分:3)
在启用自动跟踪的情况下尝试两个选项,并查看哪些一致性越少。我认为他们都会表现相同,但对我来说,rownum示例更容易阅读。
例如:
SQL> create table t1 as select object_name from all_objects;
Table created.
SQL> create index t1_idx1 on t1 (object_name);
Index created.
SQL> set autot on
SQL> select 1 from t1 where object_name = 'TOP_N' and rownum = 1;
1
----------
1
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
519 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select 1 from dual where exists (select object_name from t1 where object_name = 'TOP_N');
1
----------
1
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
519 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
答案 1 :(得分:1)
stackoverflow上有类似的问题。
Adam Musch在此声明没有真正的区别: The fastest way to check if some records in a database table?
这是关于rownum = 1性能的另一个主题: Under what conditions does ROWNUM=1 significantly increase performance in an "exists" syle query
但是,我在未编制索引的表上尝试了两种方法,并且EXISTS方法的成本略高:
显然,更高的计划是由于需要额外的DUAL呼叫。
示例:
CREATE TABLE rownum_test (x)
AS SELECT rownum FROM all_objects;
DECLARE
v_exists NUMBER;
BEGIN
FOR v_i IN 1..34050 LOOP
SELECT 1
INTO v_exists
FROM dual
WHERE EXISTS (SELECT 1 FROM rownum_test WHERE x = v_i);
END LOOP;
END; -- 13,2 seconds
DECLARE
v_exists NUMBER;
BEGIN
FOR v_i IN 1..34050 LOOP
SELECT 1
INTO v_exists
FROM rownum_test
WHERE x = v_i AND rownum = 1;
END LOOP;
END; -- 13,3 seconds
另一方面,测试显示ROWNUM方法略慢 - 但可能是我的简单测试数据不够好。
在Oracle 11G R2上进行测试。