Будет ли оператор 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 перед загрузкой, что может сократить генерацию архивного журнала почти до нуля, но, конечно, вам нужно понимать последствия этого.
- вам нужно будет сделать резервную копию затронутых файлов данных
- вам может потребоваться выполнить некоторые действия по восстановлению резервной базы данных
- вам нужно перестроить эти индексы
Как и большинство других вещей, это в основном анализ затрат и выгод.