Как я могу удалить просроченные данные из огромной таблицы, не выходя из-под контроля файла журнала? - PullRequest
7 голосов
/ 08 мая 2011

У меня огромная таблица (3 миллиарда строк), которая, к сожалению, содержит в основном данные с истекшим сроком. Я хочу просто удалить все эти просроченные строки и оставить остальные.

Я могу выполнить инструкцию следующим образом:

delete from giganticTable where exp_date < getDate()

План выполнения так или иначе оценивает, что будет удалено около 400 миллионов строк.

При выполнении это не только не завершается через час, но и размер файла журнала транзакций базы данных также увеличивается с 6 до 90 ГБ. Обратите внимание, что база данных находилась в модели восстановления с массовой регистрацией, пока это происходит. В конце концов я отменил этот запрос, так как уверен, что должен быть лучший способ сделать это.

У меня есть несколько таблиц, с которыми мне нужно выполнить аналогичную операцию. Какой самый быстрый и самый экономичный способ просто удалить эти строки, если у меня нет абсолютно никакого желания восстанавливать их?

Обратите внимание, что я использую Microsoft SQL Server 2005.

Ответы [ 3 ]

9 голосов
/ 08 мая 2011

Я обнаружил, что при удалении из таблицы с большим количеством строк полезно удалять строки в пакетах, скажем, 5000 или около того (обычно я проверяю, какое значение работает быстрее всего, иногда это 5000 строк, иногда 10000,так далее.).Это позволяет быстро завершить каждую операцию удаления, вместо того, чтобы долго ждать, пока один оператор выбьет 400 миллионов записей.

В SQL Server 2005 должно сработать что-то вроде этого (сначала проверьте, конечно):

WHILE EXISTS ( SELECT * FROM giganticTable WHERE exp_date < getDate())
BEGIN
  DELETE TOP(5000) FROM giganticTable WHERE exp_date < getDate()
END

Я бы посмотрел, что удаление в пакетах влияет на размер файла журнала.Если он все еще взрывает журналы, вы можете попробовать изменить модель восстановления на Simple , удалить записи, а затем переключиться обратно на Bulk Logged, но только если система может допустить потерю некоторых последнихданные.Я бы определенно сделал полную резервную копию, прежде чем пытаться эту процедуру.Этот поток также предполагает, что вы можете настроить задание на резервное копирование журналов только с указанным усечением, что может быть другим вариантом.Надеюсь, у вас есть экземпляр, который вы можете протестировать, но я бы начал с пакетного удаления, чтобы увидеть, как это влияет на производительность и размер файла журнала.

3 голосов
/ 08 мая 2011

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

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

Если вы используете автоинкрементные первичные ключи, вам нужно будет заставить поле взять исходные ключи (чтобы у вас не возникало проблем позже).

1 голос
/ 07 августа 2013

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

  1. Разделите работукак говорит rsbarro.Вы, вероятно, не нуждаетесь в операторе while - вы можете сделать это за несколько дней.
  2. Напишите дату явно как:

    delete from giganticTable where exp_date < '2013-08-07'
    
  3. Я не делаюиметь хорошее представление об огромном бревне, кажется, не очень хороший способ сделать.
...