При обследовании базы нередко видишь незакрывающиеся регистры накопления с момента начала работы системы. Всегда есть два варианта: первый - закрываем ежемесячно регистр в ноль и настраиваем бизнес процесс так, чтобы этот регистр правильно использовался, второй вариант - этот регистр не использовался и не будет использоваться в данной конфигурации. Второму варианту я и хочу посвятить данную статью.
Конечно, многие скажут "А что тут делать, убей все записи в регистре и все хорошо", но тут возникает другое условие, это нехватка места на диске для проведения данной операции, т.к. при удалении всех записей в регистре и пересчете итогов лог раздувается до небывалых размеров.
Сразу же рождается решение, удалять записи регистра порциями, что я изначально и делал:
Запрос = Новый Запрос("ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 100
|НДСПредъявленный.Регистратор
|ИЗ
|РегистрНакопления.НДСПредъявленный КАК НДСПредъявленный");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НаборЗаписей=РегистрыНакопления.НДСПредъявленный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Записать();
КонецЦикла;
После каждой порции удаленных записей необходимо смотреть на лог, а вдруг сильно увеличился. Берем и зацикливаем данную процедуру , смотрим на размер лога, как только достиг определенного размера останавливаем выполнение, делаем шринк лога. И так пока не удалим все записи.
Очистив записи, нужно пересчитать итоги, а объем таблицы итогов обычно в разы больше, чем размер очищенного регистра. При использовании стандартного механизма пересчета итогов, опять возникает проблема нехватки места на диске.
Для этого я реализовал следующую процедуру:
ДатаИтогов1 = РегистрыНакопления.НДСПредъявленный.ПолучитьПериодРассчитанныхИтогов();
ПланируемаяДатаИтогов = ДобавитьМесяц(ДатаИтогов1,-1);
РегистрыНакопления.НДСПредъявленный.УстановитьПериодРассчитанныхИтогов(ПланируемаяДатаИтогов);
Данная процедура уменьшает период рассчитанных итогов на 1 месяц, тем самым порционно уменьшает количество записей в таблице итогов. Ну и здесь так же, как и с регистром, зацикливаем и ждем увеличения размера лога до определенного размера.
Но на этом я не успокоился, как говорится "Лень - двигатель прогресса", мне не хотелось сидеть и смотреть за логом, увеличился он или нет, поэтому было принято решение, что лог будет чистится автоматически при достижении определенного размера.
Для этого я написал простенькую функцию, которая после очистки очередной порции подсчитывает размер лога и сравнивает его с заданным значением, и если размер лога вырос подключается к базе (MSSQL) и выполняет команду
dbcc shrinkfile (DB_log) --Очистка лога.
После такой реализации можно спокойно запускать полученную обработку и идти домой, зная что место на диске не кончится.
Вышеописанная реализация хорошо подходит для регистров с небольшим количеством записей, как и говорилось выше. Но если записей несколько миллионов, то это долго.
Для увеличения скорости удаления записей, я узнал название таблицы в базе MSSQL, зашел в базу и очистил данную таблицу, следующей командой
TRUNCATE TABLE _AccumRg1923
, где "_AccumRg1923" мой регистр. После чего я вызвал вышеописанную обработку и почистил итоги.
Сразу же скажу, что не стоит очищать таблицу итогов таким способом. После применения данного метода для таблицы итогов, у меня начали вылетать ошибки при проведении документов.
Ну и в конце статьи хочу сказать про функции УстановитьИспользованиеИтогов() , УстановитьИспользованиеТекущихИтогов(). Ими стоит пользоваться, когда ты точно уверен, что размер лога не заполнит весь объем свободного пространства на диске.
P.S.: Это моя первая статья, прошу не судить строго.