Understand the difference between IN and EXISTS in subqueries

 

Oracle Tip: Understand the difference between IN and EXISTS in subqueries

Builder.com

Choosing the right clause in complex queries can have a large effect on performance. Determine which to use in your code

When coding a SQL statement with tables in master-detail relationships, it's common to have to decide whether to write the query using the WHERE EXISTS (. . .) clause or the WHERE value IN (. . .) clause. You may resist using WHERE EXISTS because it has the awkward syntax of returning a value, which you always ignore.

However, there's a difference when using rule-based optimisation. You can determine the performance of a rule-based query by understanding which table is the driving table and how many rows each part returns.

When you write a query using the IN clause, you're telling the rule-based optimiser that you want the inner query to drive the outer query (think: IN = inside to outside). For example, to query the 14-row EMP table for the direct reports to the employee KING, you could write the following:

select ename from emp e
    where mgr in (select empno from emp where ename = 'KING'); 
Here's the EXPLAIN PLAN for this query:

OBJECT     OPERATION
---------- ----------------------------------------
                 SELECT STATEMENT()
                  NESTED LOOPS()
EMP                TABLE ACCESS(FULL)
EMP                 TABLE ACCESS(BY INDEX ROWID)
PK_EMP               INDEX(UNIQUE SCAN) 
This query is virtually equivalent to this:

select e1.ename from emp e1,(select empno from emp where ename = 'KING') e2
    where e1.mgr = e2.empno; 
You can write the same query using EXISTS by moving the outer query column to a subquery condition like this:

select ename from emp e
    where exists (select 0 from emp where e.mgr = empno and ename = 'KING'); 
When you write EXISTS in a where clause, you're telling the optimiser that you want the outer query to be run first, using each value to fetch a value from the inner query (think: EXISTS = outside to inside).

The EXPLAIN PLAN result for the query is:

OBJECT     OPERATION
---------- ----------------------------------------
                 SELECT STATEMENT()
                  FILTER()
EMP                TABLE ACCESS(FULL)
EMP                 TABLE ACCESS(BY INDEX ROWID)
PK_EMP               INDEX(UNIQUE SCAN) 
This is virtually similar to the PL/SQL code:

set serveroutput on;
declare
    l_count integer;
begin
    for e in (select mgr,ename from emp) loop
        select count(*) into l_count from emp
         where e.mgr = empno and ename = 'KING';
        if l_count != 0 then
            dbms_output.put_line(e.ename);
        end if;
    end loop;
end; 
To determine which clause offers better performance in rule-based optimisation, consider how many rows the inner query will return in comparison to the outer query. In many cases, EXISTS is better because it requires you to specify a join condition, which can invoke an INDEX scan. However, IN is often better if the results of the subquery are very small. You usually want to run the query that returns the smaller set of results first.

Some people avoid the EXISTS clause because of the requirement to return a result from the query -- even though the result is never used. Depending on personal style, people often use 'X,' 1, 0, or null. From looking at the EXPLAIN PLAN output, it appears that the optimizer throws out whatever value you enter and uses 0 all the time. Many developers get into the habit of always entering some constant value.

If you want to run your own tests, or see other examples, here are the two scripts I used:

Scott Stephens worked for Oracle for more than 13 years in technical support, e-commerce, marketing, and software development.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值