В процессе работы с конфигурацией «Управление торговлей» редакции 10.3 системный администратор и программист часто сталкиваются с разрастанием технических регистров. Одним из таких является независимый непериодический регистр сведений ОбъектыДоступаДокументов. В данной статье мы разберем, как очистить этот регистр от лишних записей, особенно для тех документов, которые уже помечены на удаление, и как сделать это максимально эффективно, не нарушая работу системы.
Прежде чем приступать к удалению, проанализируем назначение этого объекта. Данный регистр является ключевым звеном механизма RLS (Record Level Security) — ограничения прав доступа на уровне записей. В нем хранится информация о том, к каким объектам доступа (например, группам контрагентов или складов) относится конкретный документ. На основании этих данных система мгновенно определяет, имеет ли право текущий пользователь видеть этот документ в списке или открывать его.
Важно понимать: если вы просто очистите записи для актуальных документов, пользователи с ограниченными правами перестанут их видеть. Однако для документов, помеченных на удаление или физически удаленных, эти записи становятся «мусором», который замедляет работу запросов и увеличивает размер базы данных.
Рассмотрим подход, который часто выбирают начинающие разработчики. Он заключается в том, чтобы прочитать весь регистр в память, перебрать его в цикле и удалить ненужные строки. Посмотрим на пример кода, предложенный в обсуждении:
Процедура КнопкаВыполнитьНажатие(Кнопка)
НаборЗаписей = РегистрыСведений.ОбъектыДоступаДокументов.СоздатьНаборЗаписей;
НаборЗаписей.Прочитать();
Для Каждого Запись Из НаборЗаписей Цикл
Док = Запись.ДокументСсылка;
Если Док.ПометкаУдаления Тогда
НаборЗаписей.Удалить(Запись);
КонецЕсли;
КонецЦикла;
НаборЗаписей.Записать();
КонецПроцедуры
Проанализируем этот метод и выясним, почему он не рекомендуется для больших баз данных:
НаборЗаписей.Прочитать() без установленного отбора загружает ВЕСЬ регистр в оперативную память сервера или компьютера. Если в регистре миллионы записей, это приведет к ошибке Недостаточно памяти и аварийному завершению работы.Записать() вы можете перезаписать актуальные данные устаревшими.Теперь разберем более профессиональный и быстрый метод. Вместо того чтобы тянуть все данные в память, мы сначала выясним с помощью запроса, какие именно документы требуют очистки, а затем точечно удалим записи только по ним. Для удаления мы будем использовать запись «пустого набора» с установленным отбором.
Рассмотрим алгоритм действий:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Регистр.ДокументСсылка КАК ДокументСсылка
|ИЗ
| РегистрСведений.ОбъектыДоступаДокументов КАК Регистр
|ГДЕ
| Регистр.ДокументСсылка.ПометкаУдаления = ИСТИНА";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем набор для конкретного документа
НЗ = РегистрыСведений.ОбъектыДоступаДокументов.СоздатьНаборЗаписей();
// Устанавливаем фильтр по измерению
НЗ.Отбор.ДокументСсылка.Установить(Выборка.ДокументСсылка);
// Записываем пустой набор (без добавления строк)
// Это физически удаляет все записи из БД, соответствующие отбору
НЗ.Записать();
КонецЦикла;
Почему этот способ лучше?
Часто в технических регистрах остаются записи, ссылающиеся на документы, которые были удалены непосредственно (через Удалить() вместо УстановитьПометкуУдаления()). В интерфейсе такие записи выглядят как <Объект не обнаружен>. Обычное обращение через точку ДокументСсылка.ПометкаУдаления для них вернет Ложь или вызовет ошибку, так как самого объекта в базе уже нет.
Выясним, как найти и удалить такие записи. Для этого в запросе нужно использовать проверку на наличие ссылки в таблице самого документа через ЛЕВОЕ СОЕДИНЕНИЕ или проверку на NULL в условиях:
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Регистр.ДокументСсылка КАК ДокументСсылка
|ИЗ
| РегистрСведений.ОбъектыДоступаДокументов КАК Регистр
|ГДЕ
| Регистр.ДокументСсылка.Ссылка ЕСТЬ NULL";
Условие Регистр.ДокументСсылка.Ссылка ЕСТЬ NULL сработает именно для тех записей, где ссылка в регистре есть, а самого документа в базе данных уже не существует. Эти «хвосты» обязательно нужно вычищать для поддержания целостности базы.
Если в вашем регистре накопились сотни тысяч лишних записей, выполнение удаления даже правильным способом может привести к резкому росту файла лога транзакций (.ldf в MS SQL Server). Чтобы избежать зависания системы, проанализируем следующие рекомендации:
НачатьТранзакцию(), делайте ЗафиксироватьТранзакцию() каждые 1000 итераций.НаборЗаписей, для точечного удаления одной строки, если известны все измерения, можно использовать МенеджерЗаписи. Однако в контексте очистки «по документу» набор с отбором остается лидером по производительности.Подведем итог: очистка регистра ОбъектыДоступаДокументов — важная процедура обслуживания 1С:УТ 10.3. Используя связку Запрос + НаборЗаписей с отбором, мы обеспечиваем стабильную работу системы и корректную работу механизмов прав доступа без лишней нагрузки на сервер.