在最坏的情况下,两个查询都可以使用两个全表扫描加散列连接(半或反)来解决。除非你的情况出现异常情况,否则我们会说230,000行。
我的猜测是field1
或field2
是可以为空的。当您使用NOT IN
构造时,Oracle必须执行昂贵的过滤器操作,该操作基本上为外部表中的每一行执行一次内部查询。这是230 000全表扫描...
您可以通过查看执行计划来验证这一点。它看起来是这样的:
SELECT
FILTER (NOT EXISTS SELECT 0...)
TABLE ACCESS FULL ...
TABLE ACCESS FULL ...
如果在任一列中没有NULL值(FIELD1,FIELD2)可以帮助甲骨文与此资料片等都可以用另一种更高效的执行策略:
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
可以更改查询的结果。看看下面的例子,并尝试两种不同地方的子句来看到了差距:
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)
这绝不是一些黄金法则,可以应用于任何使用NOT IN的查询。 –