我有一个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
计划。
请注意,历史表是带索引的分区表。
无论如何我可以对此进行优化吗?
感谢。
答案 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);
您必须使用您的数据集进行测试,以找出最适合您的解决方案。
注意:我不希望新查询(您选择的任何一个)与原始查询一样高效。