oracle不在查询中需要比查询更长的时间

时间:2014-04-24 07:48:57

标签: oracle

我有2个表,每个表有大约230000条记录。当我进行查询时:

select count(*) 
from table1 
where field1 in (select field2 from table2). 

大概需要0.2 second

如果我使用相同的查询,只需将in更改为not in

select count(*) 
from table1 
where field1 NOT in (select field2 from table2). 

never ends

为什么?

4 个答案:

答案 0 :(得分:2)

这是扫描和搜索之间的区别。 当你要求“IN”时,你会特别要求这些值。 这意味着数据库引擎可以使用索引来查找正确的数据页。

当您要求“NOT IN”时,您会询问除这些值以外的所有值。 这意味着数据库引擎必须扫描整个表/索引以查找所有值。

另一个因素是数据量。 IN查询可能涉及的数据少得多,因此I / O比NOT IN少得多。

将它与电话簿进行比较,如果您希望只有名为史密斯的人,您可以选择史密斯的部分并将其返回。您不必阅读本书之前的任何页面或史密斯部分之后的任何页面。 如果你要求所有非史密斯 - 你必须阅读史密斯和史密斯之前的所有页面。 这说明了搜索/扫描方面和数据量方面。

答案 1 :(得分:0)

在最坏的情况下,可以使用两个全表扫描和一个散列连接(半连接或反向连接)来解析两个查询。我们正在谈论23万行的几秒钟,除非你的情况有异常情况发生。

我的猜测是field1field2可以为空。当您使用NOT IN构造时,Oracle必须执行昂贵的过滤操作,该操作基本上对外层表中的每一行执行一次内部查询。这是230 000全表扫描...

您可以通过查看执行计划来验证这一点。它看起来像是:

SELECT
   FILTER (NOT EXISTS SELECT 0...)
      TABLE ACCESS FULL ...
      TABLE ACCESS FULL ...

如果任一列(field1,field2)中没有NULL值,您可以使用这条信息帮助Oracle,以便可以使用另一种更有效的执行策略:

select count(*) 
 from table1 
 where field1 is not null
   and field1 not in (select field2 from table2 where field2 is not null)

这将生成一个类似于:

的计划
SELECT 
   HASH JOIN ANTI
      FULL TABLE SCAN ...
      FULL TABLE SCAN ...

...或者您可以将构造更改为NOT EXISTS(将生成与上面相同的计划):

select count(*) 
  from table1 
 where not exists(
          select 'x' 
            from table2 
           where table2.field2 = table1.field1
       );

请注意,从NOT IN更改为NOT EXISTS可能会更改查询结果。看看下面的例子并尝试两个不同的where子句来看看差异:

with table1 as(
   select 1    as field1 from dual union all
   select null as field1 from dual union all
   select 2    as field1 from dual
)
,table2 as(
   select 1    as field2 from dual union all   
   select null as field2 from dual union all
   select 3    as field2 from dual
)
select * 
  from table1
 --where field1 not in(select field2 from table2)
  where not exists(select 'x' from table2 where field1 = field2)

答案 2 :(得分:0)

尝试:

   SELECT count(*) 
     FROM table1 t1
LEFT JOIN table2 t2 ON t1.field1 = t2.field2
    WHERE t2.primary_key IS NULL

答案 3 :(得分:0)

用户不存在更好,因为使用行搜索时间不长