При работе с 1С часто возникает задача очистки регистров сведений от устаревших данных. Особенно актуально это для периодических регистров, где записи накапливаются ежедневно. Однако начинающие разработчики часто сталкиваются с техническим ограничением платформы: объект РегистрСведенийНаборЗаписей не позволяет устанавливать отбор по периоду в виде диапазона (больше или меньше определенной даты). В данной статье мы разберем, как эффективно решить эту задачу, используя комбинацию запросов и механизмов работы с наборами записей.
Рассмотрим стандартный механизм работы с объектом РегистрСведенийНаборЗаписей. Когда мы создаем набор, мы обязаны установить значения отбора для всех измерений, по которым мы хотим произвести действие. Однако, согласно спецификации системы 1С:Предприятие, отбор в наборе записей регистра сведений может быть установлен только на равенство. Мы не можем написать Отбор.Период.ВидСравнения = ВидСравнения.Больше, как это делается в динамических списках или построителях отчетов.
Попытка установить значения ЗначениеС и ЗначениеПо для периода в наборе записей не приведет к желаемому результату при вызове метода Записать(). Система выдаст ошибку или проигнорирует неверно заданные параметры. Поэтому для удаления данных за интервал нам потребуется алгоритм, который «разбивает» общую задачу на серию мелких операций удаления по конкретным датам.
Разберем наиболее надежный и производительный способ решения задачи. Он заключается в том, чтобы сначала определить все уникальные моменты времени (даты), на которые в регистре есть записи, а затем для каждого такого момента выполнить запись пустого набора.
Рассмотрим пошагово, как это реализовать. Сначала подготовим запрос для получения списка дат, начиная с которых нам нужно очистить регистр.
// Определяем начальную дату очистки
ДатаНачала = Дата(2020, 01, 01);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| МойРегистр.Период КАК Период
|ИЗ
| РегистрСведений.МойРегистр КАК МойРегистр
|ГДЕ
| МойРегистр.Период >= &ДатаНачала";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаПериодов = РезультатЗапроса.Выбрать();
Обратите внимание на использование ключевого слова РАЗЛИЧНЫЕ. Это критически важный момент для оптимизации. Если в одну и ту же секунду (или день, в зависимости от периодичности) записано множество строк, без этого слова запрос вернет все строки, и цикл будет выполняться избыточное количество раз для одной и той же даты. Альтернативный вариант — использовать конструкцию СГРУППИРОВАТЬ ПО.
Далее реализуем цикл по полученным периодам:
Пока ВыборкаПериодов.Следующий() Цикл
// Создаем набор записей для каждой уникальной даты
НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
// Устанавливаем жесткий отбор на конкретный момент времени
НаборЗаписей.Отбор.Период.Установить(ВыборкаПериодов.Период);
// Записываем пустой набор.
// Поскольку мы не добавляли в него записи,
// метод Записать() удалит все существующие в базе записи,
// соответствующие данному периоду.
НаборЗаписей.Записать();
КонецЦикла;
Проанализируем ситуацию, когда записей в регистре миллионы. Вышеописанный метод будет работать, но он может вызвать значительную нагрузку на сервер БД и лог транзакций. Чтобы процесс прошел гладко, стоит внедрить следующие улучшения:
ЗафиксироватьТранзакцию() и НачатьТранзакцию(). Это освободит ресурсы сервера и не даст переполниться логам SQL.БлокировкаДанных на удаляемый диапазон.ФоновыеЗадания.Выполнить().Важно помнить, что описанный выше метод с НаборЗаписей.Отбор.Период.Установить() подходит только для независимых регистров сведений. Если ваш регистр является подчиненным регистратору, удаление записей напрямую по периоду запрещено логикой системы 1С.
В случае подчиненного регистра алгоритм изменится следующим образом:
Регистратор за нужный интервал времени.Регистратор.Иногда администраторы баз данных предлагают использовать команду DELETE или TRUNCATE напрямую в консоли СУБД (MS SQL, PostgreSQL). Рассмотрим подробнее последствия такого шага. Хотя это самый быстрый способ очистки таблицы, он крайне опасен. Прямое вмешательство в обход объектной логики 1С может привести к рассогласованию индексов, нарушению ссылочной целостности и некорректной работе виртуальных таблиц (таких как «СрезПоследних»). Используйте этот метод только в исключительных случаях, предварительно создав полную резервную копию базы данных.
После завершения процесса массового удаления рекомендуется выполнить несколько регламентных операций. Во-первых, проверьте актуальность данных в виртуальных таблицах. Во-вторых, если база работает на SQL-сервере, полезно выполнить обновление статистики (Statistics Update), так как распределение данных в таблице регистра после удаления существенно изменится, и оптимизатор запросов может начать работать неэффективно.
Мы рассмотрели основной и наиболее правильный с точки зрения архитектуры 1С способ удаления данных. Помните, что аккуратная работа с наборами записей гарантирует целостность вашей информационной системы и отсутствие «битых» ссылок или зависших итогов.