【问题标题】:Speed up updates on Oracle DB which a lot of records加快更新大量记录的 Oracle DB
【发布时间】:2018-06-02 21:42:21
【问题描述】:

我必须更新大约有 9300 万条记录的表,开始时数据库每 5 秒更新 10k 条记录,现在更新了大约 6000 万条记录后,更新下 10k 条记录需要 30-60 秒,不知道为什么我必须更新为空的列。
我使用循环提交每 10 k 条记录:

  LOOP
    UPDATE TABLE
    SET DATE_COLUMN = v_hist_date
    WHERE DATE_COLUMN IS NULL
          AND ROWNUM <= c_commit_limit
          AND NOT_REMOVED IS NULL;

    EXIT WHEN SQL%ROWCOUNT = 0;
    COMMIT;
  END LOOP;

你有什么想法为什么它变慢了,以及如何加快这个更新速度?

【问题讨论】:

  • 是的,它是 PL/SQL 代码的一部分
  • 为什么?我有空值的列,当它将全部更新时,它将在更新返回 0 行时退出,它在较小的表上工作,例如1-2 百万条记录,花费的时间少得多,但也有更新的数据库版本

标签: oracle optimization plsql sql-update query-optimization


【解决方案1】:

更新也是查询。您尚未发布解释计划,但鉴于您正在过滤为空的列,您的语句似乎很可能正在执行全表扫描。这当然符合你描述的行为。

发生的事情是这样的。 FTS 的第一个循环几乎立即找到符合 WHERE 标准的 10000 行。然后退出循环并重新开始。这次 FTS 在找到下一个可以更新的 10000 行之前再次读取相同的块,包括它在上一次迭代中更新的块。等等。每个循环需要更长的时间,因为全表扫描必须为每个循环读取更多的表。

这是在循环内随机提交的惩罚之一。现在对您来说可能为时已晚,但更好的方法是跟踪索引列,例如主键。使用这样的跟踪键将允许索引扫描跳过您已经访问过的行。

【讨论】:

  • 最好的方法是进行一次更新,而不是当前进行的批量更新,确保 UNDO 表空间的大小适当。
  • @boneist - 我有点同意你的观点,但我认为在这种情况下很难定义“最佳”,没有更多细节。在一个语句中更新 93m 行的相当大块的问题是它有崩溃的风险;如果发生这种情况,我们就会失去所有的工作,不得不重新做一遍。从好的方面来说,我们获得了交易完整性。还有其他选项 - 例如设置可能合适的默认值 - 再次取决于(未指定)目标。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 2018-10-21
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多