Я не совсем уверен, что это повлияет на ваше время выполнения, но я не могу повредить. Далее ваш код указывает на пару заблуждений.
- Сначала инструкция FORALL не создает al oop. Он запускает один включенный 1 раз, обрабатывая всю коллекцию.
- Это также означает, что ваш интервал фиксации НЕ 1000, как вы указали, а 1 МБ.
- Индексная переменная (i) в оператор является локальным для этого оператора и может быть доступен только в рамках оператора forall. Таким образом, объявленная переменная i не является переменной, используемой в forall, и, следовательно, не требуется. Нет ошибки из-за правил области видимости.
- Поскольку после выхода из l oop фиксация не выполняется, последний набор не будет зафиксирован, если количество строк не будет кратным интервалу фиксации. В вашем случае с интервалом фиксации строки 1M, если у вас 8 999 999 строк, то будет зафиксировано только 8M.
Имея все это в виду, вы можете попробовать:
declare
type tab_type is table of rowid;
tab_id tab_type;
k_buffer_limit constant pls_integer := 10000;
cursor c1 is
select /*+ parallel(na,DEFAULT) */
rowid
from sample_table na
for update skip locked;
begin
open c1;
loop
fetch c1 bulk collect into tab_id limit 10000
forall i in 1..tab_id.count
update sample_table
set col1 = 'XXX'
, col2 = 'XXX'
, col3 = 'XXX'
, col4 = 'XXX'
, col5= 'XXX'
, col6 = 'XXX'
where rowid = tab_id(i);
commit;
exit when tab_id.count < k_buffer_limit;
end loop;
close c1;
end;
Массовый сбор / обработка данных - это компромисс между переключением контекста и использованием памяти. Хотя сокращение переключения контекста - хорошая вещь, это может быть преодолено требованиями к памяти. Ваш процесс может идти в ожидании, чтобы получить достаточно памяти. Вы можете улучшить производительность, уменьшив размер буфера
.