3

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

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

这个对吗?有人可以证实这一点。

提前致谢

4

2 回答 2

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
于 2013-10-01T21:07:14.463 回答
1

stackoverflow 上有类似的问题。

Adam Musch 在这里指出没有真正的区别: 检查数据库表中是否有记录的最快方法?

这是关于 rownum = 1 性能的另一个主题: 在什么情况下,ROWNUM=1 会显着提高“exists”样式查询中的性能

但是,我在未索引的表上都进行了尝试,并且 EXISTS 方法的成本略高:

ROWNUM 进近计划 存在进近计划 显然,更高的计划是由于额外需要 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 上进行测试。

于 2013-10-01T21:10:13.910 回答