В практике разработки на платформе 1С часто встречается ситуация, когда код, идеально работающий под учетной записью администратора, начинает существенно «тормозить» у обычных пользователей. Особенно ярко это проявляется при работе с табличными частями крупных объектов, таких как Ресурсные спецификации в ERP или сложные документы в УТ 11. Рассмотрим причины этой проблемы и способы её эффективного решения.
Разберем внутренние механизмы платформы. Основная причина медленной работы метода Найти() у обычных пользователей заключается в работе механизма RLS (Record Level Security) — ограничении доступа на уровне записей. Когда программист вызывает метод Найти() у табличной части объекта (например, СправочникОбъект или ДокументОбъект), платформа выполняет следующие действия:
В случае, описанном в теме, ситуация усугубляется использованием рекурсии. Если поиск в одной табличной части из-за RLS занимает даже 0.5 секунды, то при рекурсивном обходе вложенных спецификаций с глубиной в 10–20 уровней, общее время ожидания легко переваливает за 30 секунд.
Самый быстрый и простой способ решить проблему, если бизнес-логика позволяет временно игнорировать ограничения прав доступа (например, в печатной форме, где данные всё равно должны быть выведены). Мы можем принудительно отключить проверку RLS для конкретного участка кода.
Рассмотрим пример реализации:
// Включаем привилегированный режим, чтобы RLS не замедлял поиск
УстановитьПривилегированныйРежим(Истина);
// Выполняем поиск в табличной части
СтрокаМаршрута = Спецификация.Маршруты.Найти(МаршрутыСварки.Сварка, "Маршрут");
// Не забываем отключить, если далее идет код, требующий проверки прав
УстановитьПривилегированныйРежим(Ложь);
Важный момент: Использование этого метода оправдано только в том случае, если вы уверены, что вывод данных не нарушает политику безопасности компании. Для печатных форм это стандартная практика.
Метод Найти() у ТабличнойЧасти (объект метаданных) работает медленнее, чем аналогичный метод у ТаблицыЗначений (универсальная коллекция в памяти). Это связано с тем, что ТаблицаЗначений не является объектом базы данных, и поиск по ней не инициирует повторные проверки прав доступа для каждой строки в контексте владельца.
Посмотрим на алгоритм оптимизации:
// Выгружаем ТЧ в таблицу значений
ТЗ_Маршруты = Спецификация.Маршруты.Выгрузить();
// Устанавливаем индекс для ускорения поиска (если строк много)
ТЗ_Маршруты.Индексы.Добавить("Маршрут");
// Теперь поиск будет работать мгновенно даже под пользователем
СтрокаТЗ = ТЗ_Маршруты.Найти(МаршрутыСварки.Сварка, "Маршрут");
Этот метод значительно ускоряет работу, так как обращение к СУБД происходит один раз при выгрузке всей ТЧ, а не при каждом вызове Найти().
Наиболее правильным и архитектурно верным способом является полный отказ от объектной техники в пользу запросов. Запросы позволяют СУБД построить оптимальный план выполнения сразу с учетом всех ограничений прав доступа.
Выясним причину, почему запрос работает быстрее: в запросе мы можем использовать конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ, которая фильтрует данные на уровне SQL-сервера за один проход. Если же мы используем рекурсию, лучше собрать все необходимые идентификаторы (ссылки) в массив и выполнить один большой запрос вместо множества мелких в цикле.
Пример оптимизированного получения данных через запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| СпецификацияМаршруты.Ссылка КАК Спецификация
|ИЗ
| Справочник.РесурсныеСпецификации.Маршруты КАК СпецификацияМаршруты
|ГДЕ
| СпецификацияМаршруты.Ссылка В(&МассивСпецификаций)
| И СпецификацияМаршруты.Маршрут = &ИскомыйМаршрут";
Запрос.УстановитьПараметр("МассивСпецификаций", МассивСсылок);
Запрос.УстановитьПараметр("ИскомыйМаршрут", МаршрутыСварки.Сварка);
РезультатЗапроса = Запрос.Выполнить();
// Далее обрабатываем результат...
Если вы столкнулись с медленной работой поиска в табличных частях под пользователями, рекомендуем придерживаться следующего алгоритма действий:
ПолучитьОбъект()) и не обращаться к их ТЧ в циклах.Найти(Значение, "ИмяКолонки") всегда указывайте конкретную колонку. Это не решит проблему RLS, но избавит платформу от необходимости сканировать все поля каждой строки.Соблюдение этих правил позволит ускорить формирование печатных форм и отчетов в десятки раз, обеспечив комфортную работу пользователей даже в самых нагруженных системах на базе 1С:Предприятие.