Почему отчет под RLS формируется в разы дольше, чем под полными правами, и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Проблема производительности отчетов при включенном ограничении прав доступа на уровне записей (RLS) — одна из самых частых и сложных в диагностике. Ситуация, когда под полными правами отчет строится за минуты, а у пользователя висит часами, требует глубокого понимания взаимодействия платформы 1С и СУБД. В данной статье мы подробно разберем реальный кейс, проанализируем причины замедления и рассмотрим методы решения.

Симптомы проблемы

Рассмотрим типичную ситуацию. У нас есть тяжелый отчет на большом объеме данных. Показатели производительности следующие:

  1. Под полными правами (Администратор): время формирования 5–7 минут.
  2. Под ограниченными правами (Пользователь): время формирования 2–3 часа.
  3. Замер производительности (SQL): сам запрос к базе данных выполняется примерно одинаковое время (4–6 минут) в обоих случаях.
  4. Наблюдение: если пользователь вручную ставит отбор на одну организацию, отчет формируется быстро.

Ключевой момент здесь — разница между временем выполнения SQL-запроса и временем выдачи результата пользователю. Если SQL отработал за 6 минут, а пользователь ждет еще 2 часа, значит, проблема находится на стороне сервера приложений 1С в процессе пост-обработки данных.

Причина №1: Получение представлений ссылочных полей

Одна из самых неочевидных причин "тормозов" после выполнения запроса — это механизм получения представлений объектов.

Когда система компоновки данных (СКД) или обычный код выводит результат, содержащий ссылочные поля (например, СправочникСсылка.Организации), платформе нужно отобразить пользователю не уникальный идентификатор (GUID), а понятное наименование.

Как это работает под полными правами:
Платформа просто делает запрос к таблице справочника и получает поле Наименование. Это происходит массово и быстро.

Как это работает под RLS:
Прежде чем показать пользователю строку "ООО Ромашка", система обязана проверить: а имеет ли право этот пользователь вообще знать о существовании "ООО Ромашка"?

Если в выборку попало 100 000 строк с разными ссылками, платформа может начать выполнять проверку прав доступа для каждой ссылки отдельно. Это может порождать тысячи микро-запросов к БД или сложные вычисления на сервере приложений, что и вызывает задержку в несколько часов после завершения основного запроса.

Решение:

  1. В тексте запроса старайтесь выбирать сразу строковые представления полей, если ссылки не нужны для расшифровки: ВЫБРАТЬ Организация.Наименование ....
  2. Используйте конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ, чтобы отсечь недоступные данные на этапе выборки, а не вывода.

Причина №2: Отсутствие индексов на полях RLS

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

Почему это важно:
Механизм RLS физически добавляет к вашему запросу конструкцию WHERE (ГДЕ). Запрос превращается из:

ВЫБРАТЬ * ИЗ Регистр

в:


ВЫБРАТЬ * ИЗ Регистр 
ГДЕ Регистр.Организация В (ВЫБРАТЬ Разрешенные...)

Если поле Организация не проиндексировано (а ресурсы регистров обычно не индексируются по умолчанию), СУБД не может быстро найти нужные записи. Ей приходится выполнять Full Table Scan (полное сканирование таблицы) для каждой проверки прав. На больших объемах данных это катастрофически снижает производительность.

Решение:
Проверьте поля, участвующие в шаблонах RLS. Если они используются в условиях соединения или фильтрации, обязательно включите для них свойство "Индексировать" в конфигураторе.

Причина №3: Сложные условия "ИЛИ" и неоптимальные шаблоны

Давайте посмотрим на структуру шаблонов RLS. Часто встречается конструкция:


ГДЕ Реквизит1 = &Параметр1 
ИЛИ Реквизит2 = &Параметр2

Конструкция ИЛИ (OR) крайне тяжела для оптимизатора запросов (особенно в PostgreSQL). Она часто приводит к отказу от использования индексов. Если RLS добавляет такие условия к каждой таблице в запросе, время выполнения растет экспоненциально.

Решение:
Старайтесь избегать ИЛИ в RLS. Если возможно, разбивайте права на разные роли или используйте регистры соответствия ключей доступа (как это реализовано в БСП — Библиотеке Стандартных Подсистем), где все доступные объекты хранятся в одной плоской таблице.

Причина №4: Программный обход RLS и проблема иерархии

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

Ситуация:
Вы берете список доступных пользователю организаций и передаете его в параметр &СписокОрганизаций. В запросе пишете:

ГДЕ Организация В (&СписокОрганизаций)

Проблема:
Пользователь не видит данных, если ему дан доступ к Группе справочника, а в документах используются Элементы, входящие в эту группу. Оператор В проверяет точное равенство ссылок. СсылкаНаЭлемент не равна СсылкаНаГруппу.

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

Решение:
При программном формировании отбора у вас есть два пути:

  1. Использовать оператор иерархии: ГДЕ Организация В ИЕРАРХИИ (&СписокОрганизаций) Внимание: это может быть медленно, так как создает дополнительные соединения или временные таблицы.
  2. Разворачивать группы программно (Рекомендуется): Перед передачей параметра в запрос, программно получите все вложенные элементы для выбранных групп и поместите их в массив/список.
    
    // Пример логики перед запросом
    МассивЭлементов = ПолучитьВсеЭлементыИзГрупп(СписокГрупп);
    Запрос.УстановитьПараметр("СписокОрганизаций", МассивЭлементов);
    
    Тогда в запросе можно оставить быстрое условие В (&СписокОрганизаций).

Итоговый чек-лист оптимизации отчета с RLS

Если вы столкнулись с подобной проблемой, выполните следующие шаги:

  1. Проверьте индексы. Убедитесь, что все поля, по которым идет ограничение доступа (Организация, Склад, Контрагент), проиндексированы в целевых таблицах (даже если это реквизиты или ресурсы).
  2. Анализируйте вывод представлений. Если SQL быстр, а отчет медленный — проблема в получении представлений ссылок. Попробуйте выбрать представления прямо в запросе.
  3. Избегайте "ИЛИ" в RLS. Проверьте шаблоны ограничений на наличие тяжелых конструкций.
  4. Аккуратнее с иерархией. При ручной фильтрации помните, что ссылка на папку не равна ссылке на элемент. Используйте В ИЕРАРХИИ или разворачивайте список элементов программно до выполнения запроса.
  5. Используйте привилегированный режим с умом. Вынос выполнения отчета в привилегированный модуль с ручным наложением фильтров — действенный метод, но он требует от разработчика полного повторения логики прав доступа вручную.
← На главную