Быстрее ли удалить существующие строки или создать правильную новую таблицу и удалить старую, зависит от множества факторов. 11 миллионов строк - это много, но это только 0,5% от общего числа строк в таблице. Вполне возможно, что воссоздание и удаление может быть намного медленнее, чем удаление, в зависимости от того, сколько индексов существует в исходной таблице, а также от того, где на страницах данных существуют строки, которые нужно удалить.
Тогда возникает вопрос, является ли исходная таблица активной или нет. Если во время этой очистки происходят вставки и обновления, копирование и удаление не будут работать без достаточного количества дополнительного кода для синхронизации таблицы после факта.
Наконец, почему необходимо, чтобы эта операция была "быстрой"? Это потому, что система должна быть отключена во время процесса? Вы могли бы написать процедуру, которая удаляет дубликаты, пока система активна, но не влияет на остальную часть системы с точки зрения использования отмены. Мы решили эту проблему в прошлом, сначала написав запрос, который собирает первичные ключи строк, которые будут удалены во второй таблице, например:
INSERT
INTO RowsToDeleteTable
SELECT PKColumn
FROM SourceTable
WHERE <conditions used to find rows to remove>
CREATE UNIQUE INDEX PK_RowsToDelete ON RowsToDeleteTable (PKColumn);
Затем у нас есть блок PL / SQL, который перебирает строки в курсоре следующим образом:
BEGIN
FOR theRow IN (SELECT PKColumn FROM RowsToDeleteTable ORDER BY 1) LOOP
<delete source table for theRow.PKColumn)
<optionally wait a bit>
commit;
END LOOP;
END;
или делает что-то вроде этого:
BEGIN
FOR theRow IN (SELECT MIN(PKColumn) FROM RowsToDeleteTable ) LOOP
<delete source table for theRow.PKColumn)
<optionally wait a bit>
DELETE RowsToDeleteTable
WHERE PKColumn = theRow.PKColumn;
commit;
END LOOP;
END;
Циклы и «SELECT MAX», очевидно, менее эффективны, но они имеют то преимущество, что позволяют вам следить за ходом операции удаления. Мы поместили немного кода ожидания в цикл, чтобы позволить нам контролировать, насколько энергично происходит операция пожирания.
Первоначальное создание RowsToDeleteTable происходит очень быстро, и у вас есть преимущество, позволяющее процессу занять столько времени, сколько вы хотите. В этом случае «дыры», оставленные в ваших экстентах при удалении, не будут слишком плохими, поскольку вы удаляете такой небольшой процент от общего объема данных.