【问题标题】:Insert procedure is working fast at first but slows down after n number of records插入过程一开始工作得很快,但在 n 条记录后速度变慢
【发布时间】:2021-07-29 05:39:38
【问题描述】:

我们在 Oracle 19c 中对表进行批量收集插入。逻辑如下

    loop 
       fetch cursor c bulk collect 
        into v_row limit 1000  --v_row is table of source_table%rowtype
        exit when (v_row.count) = 0;
        for i in v_row.first .. v_row.last 
         loop
         --do processing here, assign v_row(i) values to v_target_table%rowtype variable
         --at the end we are extending a nested table and populating it with this v_target_table row
         v_tar_tab.extend;
         v_tar_tab(v_tar_tab.count) := v_target_table;
         end loop;
    end loop;
    --insert with forall
    forall i in v_tar_tab.first .. v_tar_tab.last 
     insert into target_table 
     values v_tar_tab (i);
    v_tar_tab := t_tar_table();  -- is table of target_table%rowtype
    commit;

问题是在这种特殊情况下,源表有 300 000 行,前 100 000 行的插入工作非常快,但此后每 1000 次提取的时间都在增加,其余 200 000 行的总时间是与前 100 000 行所花费的时间相比太大了。 为了看到这一点,我们添加了一个计数器变量,并在每次获取时将此计数器变量增加 1000,并将此计数器的迭代次数和值记录在我们的日志表中。在第 95 次到第 100 次迭代后,获取并处理了 100 000 行,处理速度变慢。

循环内没有提交,目标表设置为无日志记录,并且在执行此插入过程之前禁用其约束和索引。我想不出任何理由为什么它在前 n 行中运行得很快,而在其余行中运行得很慢。关于应该改变什么的任何想法?

如果需要注意,游标 c 中的 select 语句与提示并行运行。我在 insert into 语句中添加了 APPEND_VALUES 提示,但它并没有改变整体行为或时间。

【问题讨论】:

    标签: oracle insert bulkinsert oracle19c


    【解决方案1】:

    查看与撤消记录相关的会话统计信息。查询开始与您从中执行提取之间的差值可能会对性能产生影响,因为我们保证返回查询开始时的记录。

    如果源表正在进行事务活动,那么我们需要在提取过程中撤消这些更改。

    视频演示了该成本here

    【讨论】:

    • 感谢您的反馈,我认为您是对的。只需手动执行该过程,并通过 v$sesstat 和 v$transaction、v$session 视图进行监控。首先,在程序执行开始时,v$transaction 的 used_Ublk 和 used_Urec 值以及 v$sesstat 的 '%- undo records applied' 的值都是 0。但是在处理了大约 50 000 行之后,它们开始显示一些值.使用了 1 个撤消块和 1 个撤消记录的值,但在执行过程时,我得到的值是 20 用于使用的撤消块和 1548 的值用于使用的撤消记录。
    • v$sesstat 显示当前活动会话的更高值(因为它是并行的,它显示了 50 个会话,其应用的撤消记录的值大于 0。最高值属于这些:事务表一致读取、回滚更改、数据块一致性读取。
    • 我认为 nologging 将有助于减少撤消。如何减少这些撤消操作?我是否应该禁用并行,因为没有在源表上执行事务,它仅用于选择但并行。只对目标表执行插入操作,不对其执行选择操作。那么为什么会有这么多的撤销呢?
    • 这些数字很小(相对于您正在处理的数据),因此原因可能在其他地方。检查 v$session_event 或使用事件 10046 获取跟踪
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 2017-06-18
    相关资源
    最近更新 更多