【问题标题】:How to improve performance of FORALL insert routine?如何提高 FORALL 插入例程的性能?
【发布时间】:2018-08-31 11:54:33
【问题描述】:

我需要在 Oracle 中通过批量收集插入所有不存在于表中的记录。我的代码在这里,太费时间了。

forall i in 1 .. arr_upd_mbr.count save exceptions
      insert into claim.member_contact(member_id_rx, addr_street, addr_apt, 
        addr_city, addr_state, addr_zip, contact_phone,
        start_dt, end_dt, gender, dob)
      select 
        arr_upd_mbr(i).member_id_rx, arr_upd_mbr(i).mbr_addr_street, arr_upd_mbr(i).mbr_addr_apt,
        arr_upd_mbr(i).mbr_addr_city, arr_upd_mbr(i).mbr_addr_state, arr_upd_mbr(i).mbr_addr_zip || arr_upd_mbr(i).zip_reserve,
        arr_upd_mbr(i).primary_phone, trunc(sysdate), arr_upd_mbr(i).elg_end_dt,
        arr_upd_mbr(i).mbr_gender, arr_upd_mbr(i).mbr_dob
      from dual
      where not exists(select 1
                       from claim.member_contact
                       where member_id_rx            = arr_upd_mbr(i).member_id_rx
                         and nvl(addr_street, '~')   = nvl(arr_upd_mbr(i).mbr_addr_street, '~')
                         and nvl(addr_apt, '~')      = nvl(arr_upd_mbr(i).mbr_addr_apt, '~')
                         and nvl(addr_city, '~')     = nvl(arr_upd_mbr(i).mbr_addr_city, '~')
                         and nvl(addr_state, '~')    = nvl(arr_upd_mbr(i).mbr_addr_state, '~')
                         and nvl(addr_zip, '~')      = nvl((arr_upd_mbr(i).mbr_addr_zip || arr_upd_mbr(i).zip_reserve), '~')
                         and nvl(contact_phone, '~') = nvl(arr_upd_mbr(i).primary_phone, '~')
                         and nvl(gender, '~')        = nvl(arr_upd_mbr(i).mbr_gender, '~')
                         and nvl(dob, v_last_date)   = nvl(arr_upd_mbr(i).mbr_dob, v_last_date)
                         and sysdate between start_dt and end_dt);
    exception
      when e_dml_errors then
        save_mem_change_exp(p_mbr_enrl_log_id_rx, 'MEMBER_CONTACT(Update)', arr_upd_mbr);
  end;

【问题讨论】:

    标签: oracle performance plsql bulkinsert


    【解决方案1】:

    在 FORALL 中执行 not exists 将严重降低批量操作带来的任何性能优势。

    您没有提供任何上下文,因此我们很难提供任何有意义的建议,但您可能会通过重写代码获得更好的性能。例如:

    1. 重新访问子查询的 WHERE 子句。您所拥有的必须运行claim.member_contact 的全表扫描。也许您可以找到一种更好的方法来识别现有地址。
    2. 在填充数组时验证现有记录的存在,并丢弃不需要的记录。那么您的 FORALL 语句将只插入新记录。
    3. 忘记 FORALL ... INSERT 并改用 MERGE;您只需要编写 WHEN NOT MATCHED THEN INSERT 分支。

    【讨论】:

    • 非常感谢您的回复。让我试试合并
    猜你喜欢
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2021-08-01
    • 1970-01-01
    相关资源
    最近更新 更多