Как оптимизировать запрос к бизнес-процессу в 1С и избежать ошибок доступа RLS

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

При разработке механизмов автоматизации бизнес-процессов в 1С программисты часто сталкиваются со снижением производительности базы данных при выполнении, казалось бы, простых запросов. Типичный сценарий: при открытии документа необходимо проверить, запущен ли по нему бизнес-процесс. Однако простой запрос к таблице бизнес-процессов начинает выполняться чрезвычайно медленно, а у пользователей без полных прав система начинает требовать права на сторонние таблицы (например, на документ «Корректировка регистров»).

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

Анализ исходной проблемы

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


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    КОЛИЧЕСТВО(Согласование.Ссылка) КАК КолВо
ИЗ
    БизнесПроцесс.CRM_БизнесПроцесс КАК Согласование
ГДЕ
    Согласование.Предмет.Ссылка = &ДокСогласование
И   Согласование.Ссылка.Дата >= &ДатаСогласования

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

Ошибка 1: Обращение через точку к реквизиту составного типа (Разыменование)

Главная причина медленной работы и требования прав на документ «Корректировка записей регистров» заключается в конструкции Согласование.Предмет.Ссылка.

Реквизит Предмет у бизнес-процессов практически всегда имеет составной тип данных. В него могут входить десятки или даже сотни различных видов документов и справочников конфигурации. Когда мы обращаемся к свойству составного поля через точку (например, .Ссылка или .Номер), платформа 1С выполняет операцию разыменования.

На уровне СУБД это транслируется в левое соединение (LEFT JOIN) со всеми таблицами, входящими в этот составной тип. Если тип реквизита Предмет включает 100 видов документов, СУБД попытается выполнить левое соединение со всеми 100 таблицами. Это приводит к следующим последствиям:

Ошибка 2: Обращение к реквизитам через поле Ссылка

Вторая ошибка содержится в строке Согласование.Ссылка.Дата >= &ДатаСогласования.

Поле Ссылка является уникальным идентификатором самой таблицы БизнесПроцесс.CRM_БизнесПроцесс, к которой мы обращаемся в секции ИЗ. Обращаясь к реквизиту Дата через Ссылка.Дата, мы заставляем платформу выполнять дополнительное неявное соединение таблицы саму с собой. Это избыточная операция, которая также увеличивает время выполнения запроса.

Пошаговое решение и оптимизация запроса

Для того чтобы исправить ситуацию, нам необходимо переписать условия в секции ГДЕ, избегая неявных соединений.

Шаг 1. Переходим на прямое сравнение ссылок.

Вместо обращения Согласование.Предмет.Ссылка = &ДокСогласование мы должны использовать прямое сравнение: Согласование.Предмет = &ДокСогласование.

Почему это работает быстро? Параметр &ДокСогласование имеет строго определенный тип (например, ДокументСсылка.Согласование). Платформа 1С анализирует тип передаваемого параметра и на уровне SQL сразу выполняет фильтрацию по идентификатору и коду типа, полностью избегая соединений со всеми остальными таблицами составного типа.

Шаг 2. Исключаем обращение через Ссылка для собственных реквизитов.

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

Посмотрим на оптимизированный вариант запроса:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    КОЛИЧЕСТВО(Согласование.Ссылка) КАК КолВо
ИЗ
    БизнесПроцесс.CRM_БизнесПроцесс КАК Согласование
ГДЕ
    Согласование.Предмет = &ДокСогласование
И   Согласование.Дата >= &ДатаСогласования

Этот простой шаг позволяет сократить время выполнения запроса с нескольких секунд (или даже минут) до сотых долей секунды.

Альтернативные и дополнительные методы оптимизации

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

Использование функции ВЫРАЗИТЬ

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

В таких случаях необходимо использовать функцию ВЫРАЗИТЬ, чтобы явно указать платформе, к какой таблице нужно обратиться:


ВЫБРАТЬ
    Согласование.Ссылка,
    ВЫРАЗИТЬ(Согласование.Предмет КАК Документ.Согласование).Дата КАК ДатаДокумента
ИЗ
    БизнесПроцесс.CRM_БизнесПроцесс КАК Согласование
ГДЕ
    Согласование.Предмет ССЫЛКА Документ.Согласование

Использование ВЫРАЗИТЬ сообщает платформе, что левое соединение нужно сделать только с одной конкретной таблицей — Документ.Согласование. Все остальные таблицы составного типа будут проигнорированы, что сохранит высокую скорость работы СУБД.

Ограничение состава типов в метаданных

Часто в типовых и доработанных конфигурациях разработчики оставляют состав типов определяемых типов (таких как ПредметПроцесса) избыточным. Туда могут по умолчанию включаться абсолютно все документы системы.

Рекомендуется регулярно проводить аудит таких типов данных в конфигураторе и исключать из них «тяжелые» технические документы (корректировки регистров, закрытия месяца, расчеты себестоимости), которые никогда не будут выступать в качестве предмета бизнес-процесса. Это существенно упростит SQL-структуру базы данных и ускорит работу всей системы в целом.

← На главную