我有这样的声明:
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id)
where exists
(select 1 from old_table t1 where t2.id = t1.id);
根据解释计划的成本是150959919.解释计划显示了一些完整的表访问,总成本类似于3000,然后更新具有基本上无限的成本。如果跑步,它确实似乎永远存在。
仅供参考,这些表每行不超过300k行。
另外,这个查询。
select
(select creation_date from old_table t1 where t2.id = t1.id)
from new_table t2;
基本上立即完成。
这可能是什么原因?
答案 0 :(得分:3)
如果你有一个你提到的格式的更新语句,那么它意味着id字段在old_table中是唯一的(否则第一个内部查询会引发错误,返回多个值以进行更新,实际上只有一个值可以处理)。因此,您可以修改您的第一个查询(删除where子句,因为它是多余的): -
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id);
由于全表扫描,上述查询可能仍需要很长时间。所以,你有两个选择: -
使用以下命令将索引应用于id字段上的old_table表。
Create index index_name on old_table(id);
将您的更新查询修改为以下(未经测试): -
update new_table t2
set t2.creation_date_utc=
(select creation_date from old_table t1 where t2.id=t1.id and rownum=1);
rownum = 1应该指示oracle在old_table中找到第一个匹配项后不再进行搜索。
我会推荐第一种方法。
答案 1 :(得分:2)
你没有old_table.id上的索引,嵌套循环连接非常昂贵。 old_table(id,creation_date)的索引最好。
答案 2 :(得分:1)
为什么不使用merge语句?我发现它在类似情况下更有效率。
merge into new_table t2
using old_table t1
on (t2.id = t1.id)
when matched then
update set t2.creation_date_utc = t1.creation_date;
答案 3 :(得分:0)
这可能更快,更等效:
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id)
where t2.id in
(select id from old_table t1);