Удаление записей регистров и пересчет итогов в условиях нехватки места на диске

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

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

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

Сразу же рождается решение, удалять записи регистра порциями, что я изначально и делал:

 
Запрос = Новый Запрос("ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 100
|НДСПредъявленный.Регистратор
|ИЗ
|РегистрНакопления.НДСПредъявленный КАК НДСПредъявленный");

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НаборЗаписей=РегистрыНакопления.НДСПредъявленный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Записать();
КонецЦикла;

 

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

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

Для этого я реализовал следующую процедуру:              

ДатаИтогов1 = РегистрыНакопления.НДСПредъявленный.ПолучитьПериодРассчитанныхИтогов();
ПланируемаяДатаИтогов = ДобавитьМесяц(ДатаИтогов1,-1);
РегистрыНакопления.НДСПредъявленный.УстановитьПериодРассчитанныхИтогов(ПланируемаяДатаИтогов);

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

Но на этом я не успокоился, как говорится "Лень — двигатель прогресса", мне не хотелось сидеть и смотреть за логом, увеличился он или нет, поэтому было принято решение, что лог будет чистится автоматически при достижении определенного размера.

 Для этого я написал простенькую функцию, которая после очистки очередной порции подсчитывает размер лога и сравнивает его с заданным значением, и если размер лога вырос подключается к базе (MSSQL) и выполняет команду

dbcc shrinkfile (DB_log) --Очистка лога.

 

После такой реализации можно спокойно запускать полученную обработку и идти домой, зная что место на диске не кончится.

Вышеописанная реализация хорошо подходит для регистров с небольшим количеством записей, как и говорилось выше. Но если записей несколько миллионов, то это долго.  

Для увеличения скорости удаления записей, я узнал название таблицы в базе MSSQL, зашел в базу и очистил данную таблицу, следующей командой 

TRUNCATE TABLE _AccumRg1923

, где "_AccumRg1923" мой регистр. После чего я вызвал вышеописанную обработку и почистил итоги.

 

Сразу же скажу, что не стоит очищать таблицу итогов таким способом. После применения данного метода для таблицы итогов, у меня начали вылетать ошибки при проведении документов.

Ну и в конце статьи хочу сказать про функции УстановитьИспользованиеИтогов() , УстановитьИспользованиеТекущихИтогов(). Ими стоит пользоваться, когда ты точно уверен, что размер лога не заполнит весь объем свободного пространства на диске.

 

P.S.: Это моя первая статья,  прошу не судить строго.

8 Comments

  1. fishca

    Знание сила! Особенная сила заключается в знании чем отличается

    — TRUNCATE TABLE и delete from table на уровне sql server

    Reply ↓
  2. fishca

    Про итоговые таблицы еще надо не забыть.

    Reply ↓
  3. ice-net

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

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

    Reply ↓
  4. Константин С.
    в условиях нехватки места на диске

    может проблема в этом? Тем более на рабочей системе.

    Reply ↓
  5. KiLLius

    А о каком логе идёт речь?

    Reply ↓
  6. semensemenbi4

    (5) Журнал транзакций — The Transaction Log

    Reply ↓
  7. KiLLius

    (6) А на время чистки записей, можно же перевести базу в тип восстановления sipmpe и тогда журнал транзакций совсем не будет расти. Просто я регулярно нечто похожим занимаюсь, и делаю именно так.

    Reply ↓
  8. semensemenbi4

    (7) На время выполнения одной транзакции в режиме восстановления simple журнал пишется, чтобы в случае чего восстановится. Когда в одной операции делается очистка регистра у которого размер больше чем объем свободной памяти, то возникает ошибка «Недостаточно места на диске».

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *