Одной из наиболее острых проблем в крупных внедрениях 1С:ERP является производительность механизмов ограничения доступа на уровне записей (Record Level Security, RLS). Ситуация, когда у пользователя с полными правами форма открывается мгновенно, а у рядового сотрудника — десятки минут, знакома многим администраторам и разработчикам. Особенно часто это проявляется в типовых обработках и списках, объединяющих данные из множества различных таблиц.
В данной статье мы подробно разберем, почему возникают такие задержки, как платформа 1С взаимодействует с SQL-сервером при использовании RLS и какие шаги необходимо предпринять для исправления ситуации.
Когда мы работаем под полными правами, платформа отправляет к СУБД «чистый» запрос. Однако, как только в дело вступают ограничения (например, по Организации или Структуре предприятия), платформа принудительно модифицирует каждый запрос, добавляя в него условия проверки прав. Рассмотрим подробнее, что происходит «под капотом».
Если в форме используется динамический список или обработка типа ДокументыПоПартнеруИСделке, запрос часто строится на основе конструкции ОБЪЕДИНИТЬ ВСЕ (UNION ALL) для десятков видов документов (Заказы, Реализации, Счета-фактуры и т.д.). При включенном RLS платформа добавляет к каждой части этого объединения свои соединения с таблицами прав. Если видов документов 25, а ограничение накладывается по двум разрезам (Организация и Подразделение), итоговый SQL-запрос превращается в «монстра» с сотнями соединений. СУБД (например, MS SQL Server или PostgreSQL) зачастую не может построить оптимальный план для такого запроса и выбирает неэффективные методы сканирования таблиц.
Проанализируем ситуацию, описанную в теме: при выборе 15 видов документов всё работает быстро, а при добавлении еще нескольких — время ожидания вырастает до 15 минут. Это классический пример «деградации плана запроса», когда количество условий переходит критическую черту, и оптимизатор СУБД сдается.
В современных версиях 1С:ERP (начиная с 2.4.5 и выше) реализован инновационный механизм — производительный режим ограничений. В отличие от «классического» режима, который вычисляет права «на лету» в каждом запросе, производительный режим использует предварительно рассчитанные данные.
Как это работает: система создает специальные регистры сведений КлючиДоступаКОбъектам, КлючиДоступаКРегистрам и другие. В этих таблицах заранее записано, к какому «ключу» относится тот или иной документ. Когда пользователь открывает список, SQL-серверу нужно лишь проверить вхождение ключа документа в список разрешенных ключей пользователя. Это на порядки быстрее сложных соединений.
Разберем по шагам, как включить этот режим:
Заполнение данных для ограничения доступа.Важно: переход на этот режим может занять длительное время (от нескольких часов до суток в зависимости от объема базы), так как системе нужно пересчитать права для всех существующих документов. Рекомендуем сначала протестировать это на копии базы.
Часто проблема кроется в использовании ВЫБРАТЬ РАЗРЕШЕННЫЕ в теле сложного запроса динамического списка. Рассмотрим, как можно оптимизировать этот механизм. Если мы используем расширение, мы можем перехватить запрос и изменить его логику.
Выясним причину тормозов в конкретном коде. Вместо того чтобы позволять платформе накладывать RLS на всё объединение, иногда эффективнее сначала получить список ссылок в привилегированном режиме (без проверок), а затем наложить фильтр только на результат. Однако в динамических списках это сделать сложно, поэтому стоит обратить внимание на структуру условий.
Если в запросе используются условия типа ИЛИ в связке с RLS, это гарантированно приведет к тормозам. Попробуем заменить конструкции ГДЕ ... ИЛИ ... на использование временных таблиц или ВЫБОР КОГДА, если это возможно в контексте вашей задачи.
Одной из самых «тяжелых» операций для RLS является проверка иерархии (например, ограничение по «Структуре предприятия», когда доступ дается на верхний узел, а пользователь должен видеть все подчиненные). SQL-сервер плохо справляется с рекурсивными запросами внутри RLS.
Проанализируем настройки доступа пользователя, который жалуется на скорость:
Если «на прошлой неделе всё летало», а сегодня тормозит — велика вероятность, что актуальность статистики SQL-сервера оставляет желать лучшего. RLS крайне чувствителен к статистике индексов.
Рекомендуем выполнить следующие действия:
snccntx (кэш параметров сеанса) в каталоге профиля пользователя, от имени которого работает сервер.Рассмотрим пример того, как платформа может транслировать запрос с RLS. Допустим, у нас есть упрощенный запрос:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
Док.Ссылка,
Док.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Док
При использовании классического RLS в SQL этот запрос превратится в нечто подобное:
SELECT
T1._IDRRef,
T1._Date_Time
FROM
_Document123 T1
WHERE
T1._Fld456 IN (SELECT AllowedID FROM #TemporaryAccessTable)
AND T1._Marked = 0
Если таких таблиц в объединении 25, СУБД вынуждена строить гигантские вложенные циклы. Поэтому, если вы видите, что типовой механизм (например, обработка ДокументыПоПартнеруИСделке) не справляется, лучшим решением будет не «ломать» типовой код, а перевести систему в режим работы с Ключами доступа, где проверка будет идти по одной проиндексированной таблице _InfoRgKeyAccess.
Подводя итог, можно сказать: для ERP 2.4 использование классического RLS на больших объемах данных практически всегда ведет к проблемам производительности. Переход на производительный режим и регулярное обслуживание индексов SQL-сервера — это «золотой стандарт» решения подобных задач.