Необходимо произвести удаление записей регистра сведений. В таких случаях часто создается и записывается пустой набор записей. Но это не оптимальный вариант…
Разберем примеры удаления записей из регистра сведений «Данные для обработки» некой конфигурации, регистр имеет одно измерение «Номенклатура«, тип Справочник.Номенклатура.
Создание и запись пустого набора
Заголовок говорит сам за себя:
&НаСервере Процедура УдалитьЗаписиНаСервере() НаборЗаписей = РегистрыСведений.ДанныеДляОбработки.СоздатьНаборЗаписей(); НаборЗаписей.Записать(Истина); КонецПроцедуры
При большом количестве записей будет расходоваться оперативная память и образуется очередь на диск.
Чтение и запись порциями
Просто берем из регистра записи порциями и обрабатываем, пока записи не кончатся:
&НаСервере Процедура УдалитьЗаписиНаСервере() Продолжать = Истина; Пока Продолжать Цикл Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1000 | ДанныеДляОбработки.Номенклатура |ИЗ | РегистрСведений.ДанныеДляОбработки КАК ДанныеДляОбработки"; Продолжать = Не Запрос.Выполнить().Пустой(); Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл НаборЗаписей = РегистрыСведений.ДанныеДляОбработки.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Номенклатура.Установить(Выборка.Номенклатура); НаборЗаписей.Записать(Истина); КонецЦикла; КонецЦикла; КонецПроцедуры
При таком варианте расходование оперативной памяти будет более рациональным, но будет много операций записи
Чтение и запись порциями в транзакциях
По сути берется предыдущий вариант, но цикл обхода записей заключаем в транзакцию:
&НаСервере Процедура УдалитьЗаписиНаСервере() Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "" + ТекущаяДата() + " Начало"; Сообщение.Сообщить(); Продолжать = Истина; Пока Продолжать Цикл Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1000 | ДанныеДляОбработки.Номенклатура |ИЗ | РегистрСведений.ДанныеДляОбработки КАК ДанныеДляОбработки"; Продолжать = Не Запрос.Выполнить().Пустой(); Выборка = Запрос.Выполнить().Выбрать(); НачатьТранзакцию(); Пока Выборка.Следующий() Цикл НаборЗаписей = РегистрыСведений.ДанныеДляОбработки.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Номенклатура.Установить(Выборка.Номенклатура); НаборЗаписей.Записать(Истина); КонецЦикла; ЗафиксироватьТранзакцию(); КонецЦикла; Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "" + ТекущаяДата() + " Завершение"; Сообщение.Сообщить(); КонецПроцедуры
Таким образом мы уменьшим количество записей в БД.
Сравнение
Сравним скорость удаления 1 000 000 записей порциями по 1 000 записей с использованием транзакций и без них. Используется файловая ИБ расположенная на жестком диске SATA 3(Специально используется жестки диск, а не SSD для более выраженного различия).
Удаление порциями: 25 минут 12 секунд
Удаление порциями с транзакциями: 15 минут 43 секунды
Спасибо вам огромное! Именно благодаря вашей статье я смогла написать обработку по очистке регистра сведений «Графики Работ по Видам Времени», удалить в одной транзакции не получалось появлялась ошибка «Нехватка памяти».
Рад, что пригодилось!
Спасибо за полезную информацию!
Алексей, пожалуйста!