Проблема низкой производительности отчетов при использовании механизма RLS (Record Level Security) — одна из самых распространенных и неприятных в практике разработчика 1С. Особенно остро она проявляется в файловых базах данных, где возможности оптимизатора запросов сильно ограничены по сравнению с SQL-системами. Рассмотрим ситуацию, когда отчет под полными правами «летает», а у рядового пользователя с ограниченным доступом — «висит» несколько минут.
Выясним, что происходит «под капотом» системы. Когда пользователь с неполными правами запускает запрос, платформа 1С автоматически модифицирует его текст, добавляя условия, прописанные в настройках прав доступа. В файловом варианте это часто превращает элегантный запрос к виртуальной таблице в тяжеловесную конструкцию с множеством вложенных соединений.
Рассмотрим основные факторы, которые заставляют отчет тормозить:
ЗаказКлиента.Склад заставляет систему проверять права не только на сам регистратор, но и на все связанные объекты.Один из самых эффективных способов обойти ограничения RLS, если бизнес-логика позволяет показать данные пользователю без проверки прав на конкретные записи, — это программное формирование отчета в привилегированном режиме. Разберем по шагам, как это реализовать в модуле объекта отчета.
Для начала переопределим стандартную процедуру ПриКомпоновкеРезультата. Нам нужно запретить стандартную обработку и запустить процесс формирования вручную, предварительно установив привилегированный режим.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Выполним предварительную проверку прав, если это необходимо по логике
// Например, проверим доступ к конкретному складу
Склад = Неопределено;
Для Каждого Строка Из Настройки.ПараметрыДанных.Элементы Цикл
Если Строка.Параметр = Новый ПараметрКомпоновкиДанных("Склад") Тогда
Склад = Строка.Значение;
КонецЕсли;
КонецЦикла;
// Включаем привилегированный режим для обхода RLS
УстановитьПривилегированныйРежим(Истина);
Если ПривилегированныйРежим() Тогда
// Сформируем отчет, используя серверную процедуру
СформироватьОтчетПривРеж(ДокументРезультат, СхемаКомпоновкиДанных, ДанныеРасшифровки, КомпоновщикНастроек);
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Затем создадим вспомогательную процедуру, которая будет отвечать за вывод данных. Важно помнить, что в СКД метод Инициализировать() процессора компоновки данных должен вызываться именно в тот момент, когда привилегированный режим активен.
Процедура СформироватьОтчетПривРеж(ТабличныйДокумент, СхемаКомпоновкиДанных, ДанныеРасшифровки, КомпоновщикНастроек) Экспорт
ТабличныйДокумент.Очистить();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Генерация макета без учета прав текущего пользователя
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки, , , Ложь);
ВнешниеНаборыДанных = Новый Структура;
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
Важный нюанс: Если вы используете веб-клиент, убедитесь, что код выполняется на сервере. Привилегированный режим не работает на клиенте.
Посмотрим на пример запроса, который часто становится причиной тормозов. Обратите внимание на поля, получаемые через точку от ссылочных типов. В условиях RLS каждое такое обращение — это потенциальное «бутылочное горлышко».
Проанализируем фрагмент кода:
ВЫБРАТЬ разрешенные
РасчетыСКлиентами.АналитикаУчетаПоПартнерам.Партнер КАК Партнер,
РасчетыСКлиентами.ЗаказКлиента.Склад КАК Склад
ИЗ
РегистрНакопления.РасчетыСКлиентами.ОстаткиИОбороты(...) КАК РасчетыСКлиентами
ГДЕ
{(ЗаказКлиента.Склад = &Склад)}
Для оптимизации рекомендуется:
ЗаказКлиента.Склад в полях выбора, лучше сделать левое соединение с соответствующим справочником или документом.ЗаказКлиента составное, обязательно используйте ВЫРАЗИТЬ(ЗаказКлиента КАК Документ.ЗаказКлиента).Склад. Это поможет платформе построить более точный запрос.ОстаткиИОбороты, а не в секцию ГДЕ.Заметим интересную особенность: иногда отчет начинает работать быстро после очистки пользовательских настроек, но через некоторое время снова замедляется. Это связано с тем, что 1С кэширует настройки компоновки и планы исполнения для конкретных комбинаций отборов.
Разберем, как с этим бороться:
%AppData%\1C\1Cv8) может временно решить проблему, но это не системный подход.Если вы работаете в современной конфигурации (например, УТ 11, ERP 2 или КА 2), проверьте настройки системы. В разделе НСИ и администрирование — Настройка пользователей и прав есть опция «Вариант работы системы прав доступа».
Существует два режима:
Переход на производительный режим часто является единственным способом заставить RLS работать быстро без переписывания кода всех отчетов.
Подведем итоги нашего анализа. Если ваш отчет тормозит только под неполными правами в файловой базе:
.), особенно в условиях и отборах.