Sql Oracle EXISTS子句Vs ROWNUM=1

Sql Oracle EXISTS子句Vs ROWNUM=1,sql,oracle,Sql,Oracle,很长一段时间以来,我一直在使用EXISTS子句来确定给定条件下给定表中是否至少存在一条记录。 例如,如果我想查看“employee”表中是否存在lastname='smith'的员工,我使用以下查询 select 1 into v_exists_flag from dual where exists (select 1 from employee where lastname = 'smith'

很长一段时间以来,我一直在使用
EXISTS
子句来确定给定条件下给定表中是否至少存在一条记录。 例如,如果我想查看“employee”表中是否存在lastname='smith'的员工,我使用以下查询

select 1
  into v_exists_flag
  from dual
 where exists (select 1 
                 from employee 
                where lastname = 'smith'
              )
这肯定比使用count(*)子句更有效

如果v_计数>0,则

但是,最近有人提到使用ROWNUM=1比使用EXISTS子句具有更好的性能,如下所示

select 1
  into v_count
  from employee
 where lastname = 'smith'
   and rownum = 1
这是正确的吗?有人能证实这一点吗


提前感谢

在启用自动跟踪的情况下尝试这两个选项,看看哪一个选项的一致性越差。我认为它们的性能大致相同,但对我来说,rownum示例更容易阅读

例如:


关于stackoverflow也有类似的问题

Adam Musch在这里指出,没有真正的区别:

下面是关于rownum=1性能的另一个主题:

但是,我在未索引的表上尝试了这两种方法,EXISTS方法的成本略高:

显然,更高的计划是由于额外需要双重呼叫

例如:

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上测试。

谢谢你们(Stephen和Przemyslaw)!嗨,普泽米斯劳-我刚刚读了亚当·马斯克的帖子。根据他的帖子-如果该列被索引,则没有显著差异。很抱歉-我错误地点击了send。继续上一条评论-如果该列被索引,则看起来他建议使用EXISTS子句。您的意思是当该列未被索引时;)(亚当·马斯克就是这么写的)。我想这应该在不同的Oracle版本和小型/中型/大型表上进行检查,包括索引和未索引的表,并比较Stephen ODonnell在其文章中提供的统计数据。
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
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