Удаление записей в таблице содержит 180 миллионов в оракуле

Друзья,

У меня есть таблицы заказов, в каждой из которых содержится минимум 100 миллионов записей. У нас запущено задание, которое вызывает хранимую процедуру, удаляющую не менее 50 000 (MIN) и 200 000 000 (MAX) записей в день.

В настоящее время я использую SQL BULK COLLECT для удаления записей из таблицы. В настоящее время удаление 50K занимает более 4 часов, что очень медленно.

После поиска в Google мы выяснили метод CTAS, т. е. создали таблицу и сохранили записи, которые нам нужны, и удалили существующую, и переименовали временную таблицу. Я НЕ МОГУ ЭТОГО СДЕЛАТЬ, ТАК КАК ЭТОТ ВАРИАНТ НЕ БЫЛ ПРИНЯТ, ТАК КАК ТАБЛИЦЫ БОЛЕЕ КРИТИЧЕСКИ.

Не могли бы вы предложить какое-то решение для улучшения производительности того же самого?

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


person Prabhu    schedule 15.05.2014    source источник
comment
Какие 50K записи удаляются? На каком основании запись выбирается для удаления?   -  person A Nice Guy    schedule 15.05.2014
comment
Что не так с удалением из ‹таблицы›, где ‹условие›? Для чего используется массовый сбор?   -  person Rene    schedule 15.05.2014
comment
Я использую FORALL для удаления. Записи удаляются на основе метки времени.   -  person Prabhu    schedule 15.05.2014
comment
Rene- Удаление записей по одной займет больше времени, особенно таблица содержит 180 миллионов. Также он генерирует больше журналов повторов и отмен. Поправьте меня, если я ошибаюсь?   -  person Prabhu    schedule 15.05.2014
comment
Каков ваш критерий удаления записей? Вы удаляете самые старые? Вы рассматривали разделение?   -  person Frank Schmitt    schedule 15.05.2014
comment
Да, я рассматриваю раздел, Том предлагает 3 варианта СЛУЧАЙ № 1: создать таблицу new_table без возможности восстановления, поскольку выберите * from old_table, где ....; удалить таблицу old_table; переименовать новую_таблицу в старую_таблицу; создать индекс old_table_idx1 для old_table(c1,c2) ​​невосстановимой параллели 5; ..... БЕЗ регистрации, просто переместите данные в новую таблицу, удалите/переименуйте старую/новую, создайте индексы как можно быстрее без регистрации. СЛУЧАЙ № 2: разделите данные, выполните параллельное удаление. Каждый раздел будет использовать свой собственный сегмент отката, каждый из которых будет выполняться параллельно. ВАРИАНТ, ОСТАВШИЙСЯ МНЕ, ИМЕЕТ РАЗДЕЛ   -  person Prabhu    schedule 15.05.2014
comment
4 часа на удаление 50 тыс. строк кажутся слишком долгими, независимо от того, как удаляются строки. Вы должны профилировать и отслеживать свой код, чтобы точно видеть, на что тратится время. Есть ли неправильное соединение, из-за которого выбор строки длится вечно? Есть ли в таблице десятки индексов, что делает удаление очень медленным?   -  person Jon Heller    schedule 15.05.2014
comment
Похоже, вы ищете решение, не поняв, в чем на самом деле проблема. Если вы не знаете, почему это происходит медленно, вы не сможете быть уверены, что ваши изменения действительно помогут, и вы можете потратить много времени и усилий без пользы (или даже усугубить ситуацию).   -  person Alex Poole    schedule 15.05.2014
comment
Jonearles - 4 часа на удаление записей в 50 таблицах.   -  person Prabhu    schedule 15.05.2014


Ответы (2)


Каковы условия удаления записей?

Может быть, вы можете создать индекс на основе функции для этой таблицы. Затем вы можете удалить записи с помощью одного простого оператора удаления. Или подумайте о разбиении таблицы. Если ваш ключ раздела умен и соответствует условию удаления, вы можете удалить или очистить старый раздел в течение нескольких секунд.

Кстати, с пакетом DBMS_REDEFINITION вы можете заменить «обычную» таблицу на разделенную даже без прерывания обслуживания.

person Wernfried Domscheit    schedule 15.05.2014

Предполагая, что у вас достаточно места на физическом диске для дублирования ваших данных, вы можете использовать следующий подход (я предполагаю, что ваша таблица называется ORDERS):

  • создайте копию ORDER_B вашей таблицы заказов с помощью CREATE TABLE orders_b AS SELECT * FROM orders
  • переименуйте исходную таблицу в ORDERS_A: ALTER TABLE orders RENAME TO orders_a
  • создайте синоним ORDERS, указывающий на ORDERS_A: CREATE SYNONYM orders FOR order_a

Все идет нормально. Ваш клиентский код теперь использует синоним ORDERS вместо физической таблицы. Теперь самое интересное (ежедневное обновление):

  • урезать ORDERS_B
  • заполните ORDERS_B INSERT /*+APPEND+*/ (вы также можете попробовать подсказку PARALLEL)
  • переключите синоним ORDERS, чтобы он указывал на ORDERS_B
  • на следующий день: повторить с ORDERS_A вместо ORDERS_B
  • повторять до бесконечности

В качестве альтернативы, вместо использования TRUNCATE/INSERT, вы можете УДАЛИТЬ таблицу и СОЗДАТЬ ее заново. Это требует дополнительной работы, так как вам также придется заново создавать индексы и гранты.

Этот метод называется переключением синонимов. Вы можете прочитать Статью Тайлера Мута о переключении синонимов, чтобы получить более полное объяснение этого.

person Frank Schmitt    schedule 15.05.2014
comment
Фрэнк: действительно отличное решение. Но, как я уже упоминал в своем первом посте, я предложил то же самое, это таблица транзакций, которая будет доступна для клиента 24 часа в сутки, 7 дней в неделю, и, следовательно, предложение было отклонено. - person Prabhu; 15.05.2014
comment
@Prabhu При таком подходе данные будут доступны круглосуточно и без выходных. - person Frank Schmitt; 15.05.2014
comment
Согласен Фрэнк, но бизнес отверг этот подход. - person Prabhu; 15.05.2014
comment
Я не думаю, что это подходящее решение - не для таких огромных таблиц. - person Wernfried Domscheit; 15.05.2014