如何提高 FORALL 插入例程的性能?
Posted
技术标签:
【中文标题】如何提高 FORALL 插入例程的性能?【英文标题】:How to improve performance of FORALL insert routine? 【发布时间】: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;
【问题讨论】:
【参考方案1】:在 FORALL 中执行 not exists
将严重降低批量操作带来的任何性能优势。
您没有提供任何上下文,因此我们很难提供任何有意义的建议,但您可能会通过重写代码获得更好的性能。例如:
-
重新访问子查询的 WHERE 子句。您所拥有的必须运行
claim.member_contact
的全表扫描。也许您可以找到一种更好的方法来识别现有地址。
在填充数组时验证现有记录的存在,并丢弃不需要的记录。那么您的 FORALL 语句将只插入新记录。
忘记 FORALL ... INSERT 并改用 MERGE;您只需要编写 WHEN NOT MATCHED THEN INSERT 分支。
【讨论】:
非常感谢您的回复。让我试试合并以上是关于如何提高 FORALL 插入例程的性能?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 APEX 应用程序的 csv 文件的批量数据插入中使用 forall 语句
使用 FORALL 和 RETURNING 插入表时如何获取 ROWID
Oracle PL/SQL 如何输出在 FORALL 语句中进行了多少次插入