Дано:
- СУБД MS SQL Server
- Регистр сведений ~80 млн записей
Задача:
- удалить ~70 млн записей регистра сведений
- удалить по условию
Решение:
Если бы мне необходимо было удалить все записи, я бы воспользовался следующей командой
USE <ИмяБазы>
truncate table <ИмяТаблицы>
*имя таблицы можно посмотреть с помощью обрабтки //infostart.ru/public/16282/
Но мне надо было удалить записи по условию, казалось бы, что может быть проще, пишем:
USE <ИмяБазы>
delete from <ИмяТаблицы> where <ИмяПоля> = <ЗначениеПоля>
Но, даже в простой (Simple) модели восстановления, все операции изменения данных пишутся в одной транзакции. Соответственно лог транзакций растет очень сильно, в моем случае мне просто не хватило места на диске.
Оптимальное решение — удалять записи порциями, напимер по 5000.
USE <ИмяБазы>
WHILE 1=1
BEGIN
DELETE top (5000) FROM <ИмяТаблицы>
where <ИмяПоля>= <ЗначениеПоля>;
if @@ROWCOUNT<1 break;
END
ROWCOUNT — Возвращает число строк, затронутых при выполнении последней инструкции. Если число строк превышает 2 миллиарда, используйте ROWCOUNT_BIG
Надеюсь, мой пост будет кому-то полезен.
Гуру SQL, снимайте кеды, прежде чем пинаться! 🙂
Спасибо!
Опечатка <ИмяПоял>
(1) Спасибо, поправил.
По рзеузльаттам илссоевадний одонго анлигсйокго унвиертисета, не иеемт занчнеия, в каокм проякде рсапжоолены бкувы в солве. Галовне, чотбы преавя и пслонедяя бквуы блыи на мсете. осатьлыне бкувы мгоут селдовтаь в плоонм бсепордяке, все-рвано ткест чтаитсея без побрелм. Пичрионй эгото ялвятеся то, что мы не чиаетм кдаужю бкуву по отдльенотси, а все солво цлиеком.
(2)Работает))))
Не стал бы я надеяться на @@ROWCOUNT
(4) Алексей, ты поделись с нами почему не стал бы? Может и я не стану после твоих аргументов 🙂
(4) У меня изначально, было такое условие цикла
Но я решил, что это не оптимально…
Потом нашел описание системной переменной ROWCOUNT и переписал запрос на тот, что в статье. Все отработало без нареканий.
(6) здесь может быть потенциальная ошибка. statement изменчив. ROWCOUNT лучше сохранить, а потом использовать в сравнении.
(7) Т.к. после операции удаления нет никаких операторов, посчитал излишним в переменную сохранять.
Если нужно удалить много больше, чем половина записей таблицы, можно и через truncate сделать. Insert и Delete примерно одинаково отрабатывают по времени. Поэтому можно сразу очистить всю таблицу и вставить оставшиеся строки. К примеру:
Показать