Как оптимизировать массовые обновления в Oracle - PullRequest
0 голосов
/ 02 марта 2019

Мне нужно обновить огромную таблицу в oracle, которая содержит ~ 40 * 10 ^ 6 записей.Количество строк, которые будут изменены, будет приблизительно 10 ^ 7.Запрос, который определяет строки, которые будут обновлены, является сложным и включает в себя объединения.Требуется 30 минут, чтобы определить идентификатор строк, которые будут обновлены.

Select p.some_id from
(select some_id, col2,col3 from t1 where col2='someVulue' and col3 ='someValue') p 
inner join (select some_id from t2 where t2.col3='someValue') q
on p.some_id=q.some_id

Теперь, чтобы выполнить обновление, мне нужно добавить еще одно объединение или использовать IN утверждение, которое еще больше ухудшит положение.

Есть ли способ распараллелить это?Или сделать пакетное обновление (обновлять 25 * 10 ^ 4 строки каждый раз)?Есть ли способ сказать оракулу, чтобы обновить только первые n строк?затем n-> 2n, затем 2n-> 3n ...?

Сценарий будет выполняться в среде production , поэтому перестройка таблицы не является альтернативой.

Обновление состоит из установки для логического столбца значения true (если это может помочь)

Ответы [ 3 ]

0 голосов
/ 03 марта 2019

Есть несколько способов.1) разбить ваш запрос на маленькие кусочки.например: разбить таблицу по первичному ключу или добавить пункт 2) если вам нужно запускать это довольно часто, вы можете рассмотреть таблицу разделов, а затем запустить параллельное обновление 3) проверить, правильно ли построены ваши индексы. Кстати, я не думаю, что30 минут - длительное время, если оно не вызывает проблем с производительностью вашего приложения или блокирует другие запросы, это вполне нормально.

0 голосов
/ 03 марта 2019

Есть ли пакетное обновление (обновлять 25 * 10 ^ 4 строки каждый раз)?Есть ли способ сказать оракулу, чтобы обновить только первые n строк?тогда n-> 2n, затем 2n-> 3n, где n здесь 10

 for loop i in 1..10
 loop
 update table1
 set column_val=x
 where rowid in (select rowid from table1
 where rownum >= (((i-1) * (25*10^4))+1) and rownum <= i*(25*10^4)
 );
 end loop;
0 голосов
/ 03 марта 2019

Самый быстрый способ выполнить масштабное обновление - это параллельный DML, например:

alter session enable parallel dml;
update /*+ parallel(16) */ some_table set some_column = 1;
commit;

Есть много маленьких ошибок, на которые стоит обратить внимание.Вам нужно иметь Enterprise Edition.UPDATE получит эксклюзивную блокировку таблицы, поэтому никто другой не сможет одновременно выполнять запись в таблицу.Ваша система должна иметь достаточно ресурсов для поддержки большого UPDATE, такого как достаточное количество повторов, отмен, ЦП, операций ввода-вывода и разумно настроенной системы.

(Возможно, вы захотите изменить число 16в моем примере это число, соответствующее вашей системе. Если вы хотите максимизировать производительность, но, возможно, за счет других процессов, установите число, равное количеству ядер.)

Параллелизм Oracle - это здоровоно это не совсем оптимизирует.Это заставляет систему работать сложнее, а не умнее.Прежде чем вы попробуете распараллелить, вы можете взглянуть на оператор SQL, который используется в UPDATE.Вы также можете попробовать использовать MERGE вместо этого.Синтаксис MERGE поначалу немного сложнее, но он может помочь избежать повторяющихся объединений и позволяет выполнять хеш-объединения, которые могут выполняться быстрее для изменения большого процента строк.

...