【问题标题】:Oracle SQL - Absurdly expensive update statement?Oracle SQL - 昂贵得离谱的更新语句?
【发布时间】:2013-01-29 17:46:38
【问题描述】:

我有这样的声明:

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;

基本上立即完成。

这可能是什么原因?

【问题讨论】:

    标签: sql oracle sql-update


    【解决方案1】:

    如果你有一个你提到的格式的更新语句,那么它意味着 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 中找到第一个匹配项后不要再进行任何搜索。

    我会推荐第一种方法。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 在这种情况下,使用 user1395 建议的 MERGE 在表之间获得更有效的连接可能会更好。
      【解决方案3】:

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

      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;
      

      【讨论】:

      • +1:合并可能会更快,因为如果任何一个表很大,那么它们之间的连接将被实现为哈希外连接。
      【解决方案4】:

      这可能更快且等效:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-30
        • 2019-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-11
        相关资源
        最近更新 更多