Оптимизировать запрос на удаление с большим количеством данных на Oracle - PullRequest
0 голосов
/ 20 марта 2012

Я работаю над оракулом 9i. У меня есть таблица с 135 000 000 записей, где каждый раздел имеет ок. 1000000 строк все проиндексировано и все.

Мне нужно удалить около 70 000 000 строк из этого как новое бизнес-требование.

Итак, я создал резервную копию строк, которые нужно удалить как отдельную таблицу.

Table1 <col1, col2........> -- main table (135,000,000 rows)

Table2 <col1, col2........> -- backup table (70,000,000 rows)

Попробовал приведенный ниже запрос на удаление.

Delete from table1 t1 where exists (select 1 from table2 t2 where t2.col1 = t1.col1)

но это занимает бесконечные часы.

затем попытался

declare
cursor c1 is 
select col1 from table2;
c2 c1%rowtype;
cnt number;
begin
cnt :=0;
open c1;
loop
    fetch c1 into c2;
    exit when c1%notfound;

    delete from table1 t1 where t1.col1 = c2.col1;
    if cnt >= 100000 then
        commit;
    end if;
    cnt:=cnt+1;
end loop;
close c1;
end;

даже он работает уже более 12 часов. и все еще не завершено.

Обратите внимание, что в таблице 1 есть несколько индексов, а в таблице 2 - индекс col1. все таблицы и индексы проанализированы.

Пожалуйста, сообщите, если есть какой-либо способ оптимизации для этого сценария.

Спасибо, ребята.

Ответы [ 4 ]

4 голосов
/ 20 марта 2012

Я помню, как сталкивался с этой проблемой ранее. В этом случае мы прибегли к этому, поскольку это сработало быстрее, чем любая другая операция удаления:

1) Создать другую таблицу с идентичной структурой

2) Вставьте в новую таблицу записи, которые вы хотите сохранить (для ускорения используйте прямую вставку пути)

3) Бросить старый стол

4) Переименовать новую таблицу

4 голосов
/ 20 марта 2012

Удаление всех индексов (резервное копирование операторов create). Используйте оператор SELECT, использованный для построения таблицы резервного копирования, создайте из нее команду DELETE. Восстановите все индексы

.
1 голос
/ 21 марта 2012

Вы говорите, что таблица разделена.Вы намерены сбросить все данные в определенных разделах?Если это так, вы сможете просто удалить 7 разделов, которые имеют 70 миллионов строк, которые вы хотите удалить.Тем не менее, я предполагаю, что ваша проблема не так проста.

Если вы можете выполнять временные коммиты, это означает, что вы не заботитесь о согласованности транзакций, наиболее эффективный подход, вероятно, что-то вродестрок

CREATE TABLE rows_to_save
    AS SELECT *
         FROM table1
        WHERE <<criteria to select the 65 million rows you want to keep>>

TRUNCATE TABLE table1;

INSERT /*+ append */
  INTO table1
SELECT *
  FROM rows_to_save;

За исключением того, что вместо создания резервной таблицы было бы эффективнее просто выполнить оператор DELETE

DELETE FROM table1
 WHERE <<criteria to select the 70 million rows you want to keep>>

Вы также можете получить выгоду от удаления илиотключение индексов и ограничений перед запуском DELETE.

0 голосов
/ 21 марта 2012

Я собираюсь ответить на это, предполагая, что дешевле фильтровать по таблице резервных копий, но, вероятно, было бы дешевле просто использовать отрицание критериев, которые вы использовали для заполнения таблицы резервных копий.

1) создать новую таблицу с той же структурой.Нет индексов, ограничений или триггеров.

2)

    select 'insert /*+ append nologging */ into new_table partition (' || n.partition_name || ') select * from old_table partition (' || o.partition_name || ') minus select * from bak_table partition (' || b.partition_name || ');'
    from all_tab_partitions o, all_tab_partitions n, all_tab_partitions b
    where o.partition_no = all( n.partition_no, b.partition_no)
      and o.table_name = 'OLD_TABLE' and o.table_owner = 'OWNER'
      and n.table_name = 'NEW_TABLE' and n.table_owner = 'OWNER'
      and b.table_name = 'BAK_TABLE' and b.table_owner = 'OWNER';
    -- note, I haven't run this it may need minor corrections in addition to the obvious substitutions

3) проверить и запустить результат предыдущего запроса

4) построить индексы, ограниченияи запускает при необходимости

Это позволяет избежать огромного количества повторов и отмен по сравнению с удалением.добавьте подсказку для прямых вставок без записи в журнал, чтобы еще больше сократить повтор - убедитесь, что резервное копирование впоследствии использует преимущества разбиения для разбиения работы на куски, которые можно отсортировать за меньшее количество проходов

Вероятно, вы могли бы пойти быстрее с параллельной вставкой+ параллельный выбор, но это, вероятно, не нужно.Просто не делайте параллельный выбор без вставки и «alter session enable параллельного dml»

...