Будет ли оператор Insert работать лучше, чем оператор слияния в Oracle

Могу я спросить, будет ли оператор Insert работать лучше, чем оператор слияния в Oracle, если нам не нужно делать какие-либо обновления?

Я понимаю, что один оператор слияния обычно является предпочтительным вариантом, если нам нужно одновременно запустить и вставить, и обновить операторы для одной и той же таблицы. Но что, если у меня есть только оператор вставки?

У меня есть 20 таких таблиц

      Create Table Txn_History nologging (
ID number,
Comment varchar2(300),
... (Another 20 columns),
Std_hash raw(1000) 
);

Alter table Txn_History add constraint Order_line_PK Primary (Std_hash);

И 20 таких промежуточных столов

      Create Table Order_line_staging nologging (
ID number,
Comment varchar2(300),
... (Another 20 columns),
Std_hash raw(1000) 
);

Alter table Order_line_staging add constraint Order_line_PK Primary (Std_hash);

Каждая таблица Txn_History теперь имеет 40 миллионов строк, и я собираюсь вставить еще 50 миллионов строк из каждой соответствующей таблицы Txn_History_staging несколькими партиями. В каждом пакете 1 миллион строк. В конце каждой итерации промежуточная таблица удаляется с оператором очистки.

Ниже приводится мое заявление о слиянии

      Merge into Txn_History Target
using Txn_History_Staging source on
    (source.std_hash = Target.std_has)
when not matched then
   insert(
      ID,
      Comment,
      ... (Another 20 columns),
      std_hash
   ),
   values
   (
       Target.ID,
       Target.comment,
       ... (Another 20 columns),
       Target.std_hash
   );

Моя база данных находится в режиме архивного журнала (FORCE_LOGGING = 'NO'), и я заметил, что каждая итерация занимает 2 часа, и все же генерируется 25-гигабайтный журнал событий архивного журнала.

Итак, я подозреваю, что оператор слияния создал архивный журнал.

Было бы лучше, если бы я вместо этого использовал следующий оператор вставки:

      insert /*+append */ into Txn_History Target
select
    *
from
   Txn_History_staging Source
where
    Source.std_hash not in (select distinct std_hash  from txn_history);

Будет ли он иметь лучшую производительность (т.е. работать быстрее И ТАКЖЕ генерировать меньше журналов)?

Заранее спасибо!

1 ответ

Решение

Скорее всего , ваш INSERT будет работать лучше, но реальное доказательство заключается в выполнении. Если вы видите HASH ANTI JOIN как механизм для получения требуемых строк, это обычно близко к оптимальному.

Создание архива является следствием изменений, записанных в базе данных, поэтому стандартное MERGE (которое заканчивается вставкой) или INSERT сгенерирует очень похожий объем архива.

Фактор дифференциации - это, скорее, подсказка ПРИЛОЖЕНИЕ. Сам по себе (на таблице со значением по умолчанию LOGGING) вы, вероятно, увидите либо

  • нет / небольшое уменьшение архивного журнала, если таблица не проиндексирована
  • некоторое сокращение архивного журнала, если таблица проиндексирована

Реальный выигрыш заключается в том, что вы сделаете таблицу NOLOGGING перед загрузкой и установите для индексов значение UNUSABLE перед загрузкой, что может сократить генерацию архивного журнала почти до нуля, но, конечно, вам нужно понимать последствия этого.

  • вам нужно будет сделать резервную копию затронутых файлов данных
  • вам может потребоваться выполнить некоторые действия по восстановлению резервной базы данных
  • вам нужно перестроить эти индексы

Как и большинство других вещей, это в основном анализ затрат и выгод.

Другие вопросы по тегам