【问题标题】:Delayed update in Oracle PL/SQLOracle PL/SQL 中的延迟更新
【发布时间】:2012-02-15 05:44:02
【问题描述】:

我有一个简单的 PL/SQL 过程,只有一个游标,然后我对其进行迭代。在每次迭代中,我都会创建一个 UPDATE 语句(在对数据执行一些业务逻辑之后)。

但是,如果有很多迭代(数万次),这可能会变得很慢,因为在每次迭代中都有一个 UPDATE 语句。

有没有办法以某种方式“延迟”这些更新,以便一次执行所有更新(因此速度更快)。

编辑:甲骨文 11

【问题讨论】:

  • 嗯,问题在于 Oracle 维护其回滚段。你在一个事务中修改的越多,它变得越慢。就不能拆分业务逻辑,每1000个UPDATEs左右加一个COMMIT;吗?
  • @sjngm,这通常是个坏主意。 Tom Kyte 对此有很多话要说,例如,asktom.oracle.com/pls/apex/…
  • @snjgm,减速不是因为回滚段,而是由迭代和选择引起的。与听起来执行的其他工作相比,回滚段的更新可以忽略不计

标签: performance oracle plsql oracle11g


【解决方案1】:

如果您不知道如何使用直接 SQL(一起避免 for 循环),那么您可能能够使用 pl/sql 的 BULK Collection 功能提高性能。

Example article here.

语法摘录

 LOOP
    FETCH c_orders
    BULK COLLECT INTO v_order_ids, v_currency_codes, v_amounts_local
    LIMIT 100;
    EXIT WHEN v_row_count = c_orders%ROWCOUNT;
    v_row_count := c_orders%ROWCOUNT;
    FOR i IN 1..v_order_ids.count LOOP
      v_amounts_usd(i) := currency_convert (v_amounts_local(i),
                                            v_currency_codes(i));
    END LOOP;
    FORALL i IN 1..v_order_ids.count
      UPDATE open_orders /* bulk bind */
      SET    amount_usd = v_amounts_usd(i)
      WHERE  order_id = v_order_ids(i);
  END LOOP;

【讨论】:

【解决方案2】:

我没有看到任何关于问题所在的分析,但我看到人们做出很多假设并得出结论。为了获得更系统的方法,我建议如下:

  • 在更新作业运行时为会话启用 10046 级跟踪,以查看大部分时间都花在了哪里
  • 在更新作业运行之前和之后获取会话级别的统计信息。

查看大部分时间都花在了哪里,并解决真正的问题。

【讨论】:

    【解决方案3】:

    尽可能尝试在更新语句中执行业务逻辑。会快很多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 2018-10-05
      • 2019-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多