В практике разработки на платформе 1С:Предприятие часто возникает ситуация, когда, казалось бы, простой запрос к небольшому регистру сведений начинает «тормозить» систему. Особенно остро это проявляется в таких конфигурациях, как 1С:Комплексная автоматизация 1.1 или УПП, и на файловых базах данных. Разберем на конкретном примере, почему обращение к полю Ссылка через точку может замедлить работу программы в несколько раз и как правильно оптимизировать такие запросы.
Рассмотрим исходную ситуацию: в системе создан самодельный регистр сведений НетДокументов, где измерение Документ имеет составной тип данных (например, ссылки на несколько видов документов). Автор темы столкнулся с тем, что запрос в подписке на событие ПриЗаписи выполняется крайне медленно. Проанализируем исходный код запроса:
Запрос.Текст ="ВЫБРАТЬ РАЗРЕШЕННЫЕ
| НетДокументов.Документ.Ссылка КАК Док
|ИЗ
| РегистрСведений.НетДокументов КАК НетДокументов
|ГДЕ
| НетДокументов.Документ.Ссылка = &Документ";
Основная причина низкой производительности здесь заключается в конструкции НетДокументов.Документ.Ссылка. Для платформы 1С обращение через точку от поля составного типа является командой на выполнение неявного левого соединения (LEFT OUTER JOIN) со всеми таблицами документов, которые входят в этот тип. Если измерение Документ может принимать значения 10 различных видов документов, СУБД будет вынуждена соединить таблицу регистра с 10 таблицами документов, чтобы проверить наличие ссылки.
Важно понимать: поле Документ само по себе уже содержит ссылку (GUID). Обращение к Документ.Ссылка избыточно и заставляет систему выполнять лишнюю работу по поиску данных в физических таблицах документов.
Для оптимизации необходимо обращаться напрямую к полю измерения. Выясним причину: когда мы пишем НетДокументов.Документ, система берет значение непосредственно из таблицы регистра. Проанализируем исправленный вариант запроса:
Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент);
Запрос.Текст ="ВЫБРАТЬ РАЗРЕШЕННЫЕ
| НетДокументов.Документ КАК Док
|ИЗ
| РегистрСведений.НетДокументов КАК НетДокументов
|ГДЕ
| НетДокументов.Документ = &Документ";
В данном случае платформа сравнивает идентификаторы (GUID) напрямую в таблице регистра. Это позволяет СУБД эффективно использовать индекс по измерению Документ, не затрагивая другие таблицы базы данных. Как отметил автор темы, такое простое изменение позволило ускорить выполнение операции в два раза.
Если логика работы в подписке на событие подразумевает проверку существования только одной конкретной записи, использование объекта Запрос может быть не самым оптимальным путем. Разберем альтернативный подход с использованием МенеджераЗаписи. Этот метод особенно эффективен в файловых базах, так как он работает напрямую с индексом первичного ключа.
Посмотрим на пример реализации:
МенеджерЗаписи = РегистрыСведений.НетДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Документ = Источник.Ссылка; // Источник - документ из подписки
МенеджерЗаписи.Прочитать();
Если Не МенеджерЗаписи.Выбран() Тогда
// Записи нет, можно создавать новую
МенеджерЗаписи.Документ = Источник.Ссылка;
МенеджерЗаписи.ЕстьДокумент = Ложь;
МенеджерЗаписи.Записать();
КонецЕсли;
Метод Прочитать() работает быстрее, чем создание, парсинг и выполнение текста запроса, так как платформа сразу обращается к нужной строке по известным измерениям.
Часто проблема «медленного запроса» проявляется не при работе пользователя в форме, а при групповом перепроведении документов или восстановлении последовательностей. Если подписка на событие содержит запрос, то при проведении 1000 документов система выполнит 1000 отдельных запросов к базе данных.
Для оптимизации таких процессов проанализируем следующие рекомендации:
ОбменДанными.Загрузка = Истина.В файловой базе данных 1С (формат .1CD) при записи любого объекта блокируется вся таблица. Если запрос внутри транзакции записи выполняется долго (из-за тех же неявных соединений), это блокирует работу других пользователей. Посмотрим, как это происходит: подписка ПриЗаписи выполняется в той же транзакции, что и запись самого документа. Чем дольше работает ваш «простой» запрос, тем дольше висит блокировка на всей таблице документов. Поэтому оптимизация каждого запроса в таких событиях критически важна для стабильности системы.
Подведем итоги: для обеспечения максимальной производительности при работе с регистрами сведений необходимо:
ГДЕ и секции ВЫБРАТЬ, если вам нужна только сама ссылка.МенеджерЗаписи для точечных проверок и модификаций.ВЫБРАТЬ РАЗРЕШЕННЫЕ в коде, который выполняется при проведении, перенося логику в привилегированные модули.