Как улучшить производительность процедуры вставки FORALL? - PullRequest
0 голосов
/ 31 августа 2018

У меня есть требование вставить все те записи, которых еще нет в таблице с массовым сбором в 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 Ответ

0 голосов
/ 31 августа 2018

Выполнение not exists в FORALL серьезно уменьшит любые преимущества в производительности от массовой операции.

Вы не предоставили никакого контекста, поэтому нам сложно дать какой-либо значимый совет, но вы можете получить лучшую производительность от переписывания кода. Например:

  1. Пересмотрите предложение WHERE подзапроса. То, что у вас там, должно быть запущено полное сканирование таблицы claim.member_contact. Может быть, вы можете найти лучший способ идентификации существующих адресов.
  2. Проверьте наличие существующих записей при заполнении массива и отбросьте те, которые вам не нужны. Тогда ваш оператор FORALL будет вставлять только новые записи.
  3. Забудьте о FORALL ... INSERT и используйте вместо него MERGE; вам нужен только код, КОГДА НЕ СОГЛАСОВАНО, ТО ВСТАВИТЬ ветку.
...