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

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

Разработчики систем на платформе «1С:Предприятие» часто сталкиваются с неприятной ситуацией: запрос, который под полными правами администратора выполняется мгновенно (за доли секунды), у обычного пользователя с ограничениями доступа на уровне записей (RLS) начинает жутко тормозить, выполняясь по 10–20 секунд и более. Особенно остро эта проблема проявляется в динамических списках документов или справочников.

В рамках этой статьи мы подробно разберем, почему возникает такая деградация производительности, рассмотрим внутренние механизмы платформы 1С и СУБД, проанализируем коварный эффект Parameter Sniffing и изучим практические методы решения проблемы.

Внутренний механизм RLS: почему раздувается SQL-запрос

Когда пользователь с ограниченными правами выполняет запрос, платформа 1С автоматически модифицирует его перед отправкой в СУБД. Даже если в исходном коде не используется ключевое слово РАЗРЕШЕННЫЕ, система все равно обязана отфильтровать данные согласно действующим правилам RLS.

В обычном (стандартном) режиме работы RLS модификация происходит «на лету». К исходному, казалось бы, простому запросу платформа принудительно добавляет многочисленные левые соединения (LEFT JOIN) и вложенные подзапросы к таблицам прав доступа, групп пользователей, видов доступа и профилей. В итоге лаконичный запрос из 10 строк превращается на стороне СУБД в сложную структуру из сотен строк кода. Для СУБД стоимость выполнения такого запроса возрастает по экспоненте, так как вместо прямого чтения таблицы ей приходится связывать огромные массивы данных.

Коварство динамических списков: ловушка «TOP N»

Наиболее критично RLS бьет по динамическим спискам. По умолчанию динамический список работает по принципу постраничной выборки, запрашивая у СУБД порции данных (например, первые 45 строк) с помощью конструкции SELECT TOP 45.

Рассмотрим, как это происходит на уровне базы данных:

  1. Под полными правами: СУБД мгновенно берет первые 45 физических строк таблицы в соответствии с установленным порядком сортировки и сразу возвращает их на клиент. Количество чтений из базы минимально.
  2. Под ограниченными правами (с RLS): СУБД обязана вернуть первые 45 именно разрешенных пользователю строк. Если вверху таблицы по порядку сортировки лежат тысячи документов, к которым у пользователя нет доступа, СУБД будет вынуждена перебрать, прочитать и отфильтровать сотни тысяч или даже миллионы строк базы данных в поисках тех самых 45 разрешенных записей. Это объясняет, почему запрос администратора может делать всего 160 чтений, а запрос пользователя с RLS — более 3 000 000 чтений.

Эффект Parameter Sniffing на стороне СУБД

Многие разработчики замечают странное поведение системы при тестировании производительности: стоит добавить пользователю немного прав, как запрос начинает «летать» за полсекунды. После возвращения прав в исходное состояние запрос продолжает работать быстро. Однако после очистки кэша планов запросов или обновления статистики СУБД производительность снова падает до 12–15 секунд.

Этот эффект в Microsoft SQL Server называется Parameter Sniffing (чувствительность к параметрам):

Ниже приведен пример концептуального SQL-запроса, в который платформа 1С превращает обычную выборку документов при наложении стандартных ограничений RLS:


SELECT TOP 45
    T1._IDRRef,
    T1._Number,
    T1._Date_Time
FROM
    _Document150 T1
LEFT OUTER JOIN _InfoReg200 T2 ON (T2._Fld201RRef = T1._Fld151RRef)
WHERE
    T2._Fld202RRef IN (SELECT _Fld301RRef FROM _InfoReg300 WHERE _Fld302RRef = @P1)

Такие вложенные конструкции крайне тяжело поддаются оптимизации стандартными средствами СУБД без точечной настройки индексов.

---

Решение 1: Анализ SQL-плана и добавление недостающих индексов в СУБД

Это самый надежный и точечный метод решения проблемы, который помог автору обсуждения. Типовые конфигурации 1С проектируются универсально, и индексы в них создаются под стандартные сценарии. Однако специфические правила RLS в вашей базе могут требовать совершенно иных индексов.

Выполним оптимизацию по шагам:

  1. Запустите SQL Server Profiler (или настройте сбор технологического журнала 1С по событиям DBMSSQL).
  2. Поймайте медленный SQL-запрос, выполняющийся от имени пользователя с RLS.
  3. Откройте полученный запрос в SQL Server Management Studio (SSMS) и запустите оценку фактического плана выполнения (шорткат Ctrl + M).
  4. Проанализируйте план выполнения. Обратите внимание на операции Index Scan (сканирование индекса) или Table Scan (сканирование таблицы), которые забирают наибольший процент стоимости запроса. Часто сама SSMS зеленым текстом подсказывает, какого именно индекса ей не хватает для ускорения выборки.
  5. Создайте недостающий составной индекс на уровне СУБД. Чаще всего требуется индекс, включающий реквизит ограничения (например, Организация или Подразделение) в сочетании с полем ссылки на объект и датой.

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

Решение 2: Переход на производительный режим RLS в БСП

Если ваша конфигурация разработана на базе современной версии «Библиотеки стандартных подсистем» (БСП 3.x), вам доступен кардинально новый механизм — Производительный (универсальный) режим работы RLS.

Рассмотрим, как работают оба режима, чтобы понять разницу:

Для включения этого режима выполните следующие действия:

  1. Перейдите в раздел администрирования прав доступа вашей конфигурации.
  2. Найдите настройки производительности RLS (в разных конфигурациях интерфейс может отличаться, но обычно это флаг «Производительный режим проверки прав» или «Ускорять работу RLS»).
  3. Активируйте настройку.
  4. Запустится фоновое задание «Обновление доступа на уровне записей». Обязательно дождитесь его полного завершения. Система должна рассчитать ключи доступа для всех существующих в базе объектов.

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

Решение 3: Оптимизация запроса динамического списка

Если предыдущие методы недоступны, мы можем облегчить жизнь СУБД, оптимизировав сам текст запроса динамического списка:

Резюме

Универсального решения «в один клик» для проблем с RLS не существует. В простых базах с небольшим объемом данных отлично помогает переход на производительный режим RLS в БСП. На крупных, высоконагруженных внедрениях наилучшие результаты дает ручной анализ планов запросов в SQL Server и точечное построение составных индексов под конкретные профили групп доступа пользователей.

← На главную