检查表中是否存在特定行数的最有效方法

时间:2015-12-18 11:19:06

标签: sql oracle performance

我有一个oracle查询,如下所示:

INSERT /*+APPEND*/ INTO historical
SELECT a.* FROM TEMP_DATA a WHERE NOT EXISTS(SELECT 1 FROM historical WHERE KEY=a.KEY)

通过查询,当我运行解释计划时,我注意到优化器选择了HASH JOIN计划并且成本相当低

但是,有一个新的请求要说明历史表中可以存在多少行以检查TEMP_DATA表,因此查询将更改为:

INSERT /*+APPEND*/ INTO historical
SELECT a.* FROM TEMP_DATA a WHERE (SELECT COUNT(1) FROM historical WHERE KEY=a.KEY) < 2

这意味着如果给定密钥(不是主键)的历史数据中存在1行记录,则仍然可以插入数据。

然而,采用这种方法,查询速度减慢很多,成本超过原始成本的10倍。我还注意到优化器现在选择NESTED LOOP计划。

请注意,历史表是带索引的分区表。

无论如何我可以对此进行优化吗?

感谢。

2 个答案:

答案 0 :(得分:1)

以下查询应该执行相同的操作,并且应该更高效:

select a.* 
  from temp_data a
  left
  join(select key, count(*) cnt
         from historical
        group
           by key
      ) b
    on a.key = b.key
 where nvl(b.cnt, 0) < 2;   

希望有所帮助

答案 1 :(得分:0)

@ DirkNM答案的替代方案是:

select a.*
from   temp_data a
where  not exists (select null
                   from   historical h
                   where  h.key = a.key
                   and    rownum <= 2
                   group  by h.key
                   having count(*) > 1);

您必须使用您的数据集进行测试,以找出最适合您的解决方案。

注意:我不希望新查询(您选择的任何一个)与原始查询一样高效。