1

我有这样的声明:

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;

基本上立即完成。

这可能是什么原因?

4

4 回答 4

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);

由于全表扫描,上述查询可能仍需要很长时间。所以,你有两个选择:-

  1. 使用以下命令对 id 字段上的 old_table 表应用索引。

    Create index index_name on old_table(id);
    
  2. 将您的更新查询修改为以下(未经测试):-

    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 中找到第一个匹配项后不要再进行任何搜索。

我会推荐第一种方法。

于 2013-01-29T02:36:52.967 回答
2

您在 old_table.id 上没有索引,并且嵌套循环连接非常昂贵。old_table(id, creation_date) 上的索引最好。

于 2013-01-29T00:18:22.533 回答
1

为什么不使用合并语句?我发现它在类似情况下更有效。

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;
于 2013-01-29T09:46:38.610 回答
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);
于 2013-01-29T00:59:57.880 回答