简体   繁体   中英

Oracle EXISTS clause Vs ROWNUM = 1

For a long time, I have been using the EXISTS clause to determine if at least one record exists in a given table for a given condition. for example - if I wanted to see if an employee by lastname = 'smith' exists in the "employee" table, I used the following query

select 1
  into v_exists_flag
  from dual
 where exists (select 1 
                 from employee 
                where lastname = 'smith'
              )

This is definitely more efficient than using the count(*) clause.

select count(*) 
  into v_count 
  from employee
 where lastname = 'smith'

if v_count > 0 then....

But, recently someone mentioned that using ROWNUM = 1 has better performance than using the EXISTS clause as shown below

select 1
  into v_count
  from employee
 where lastname = 'smith'
   and rownum = 1

Is this correct? Can someone confirm this.

Thanks in advance

Try the two options out with autotrace enabled and see which ones does the fewer consistent gets. I think they will both perform about the same, but for me, the rownum example is easier to read.

Eg:

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

There were similiar question on stackoverflow.

Here Adam Musch states that there is no real difference: The fastest way to check if some records in a database table?

Here is another topic about rownum = 1 performance: Under what conditions does ROWNUM=1 significantly increase performance in an "exists" syle query

However, I tried both on an unindexed table and the cost of the EXISTS approach is slightly higher:

ROWNUM进近计划EXISTS进近计划 Obviously the higher plan is due to the additional need for DUAL call.

Example:

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

The test, on the other hand, shows that ROWNUM approach is slightly slower - but it may be that my simple test data is not good enough.

Testing on Oracle 11G R2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM