Что считается неявным запросом к базе данных в цикле 1С и как это оптимизировать

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает вопрос о так называемых «неявных» или «черных» запросах. Это ситуации, когда в коде нет явного использования объекта Запрос, но система все равно обращается к базе данных (SQL серверу) для получения данных. Если такие обращения происходят внутри цикла, производительность системы может упасть в десятки и сотни раз. Рассмотрим подробнее, какие конструкции кода вызывают скрытые обращения к БД и как правильно организовать работу с данными.

Обращение к реквизитам через точку: почему это «черный» запрос

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


Для каждого СтрТовары Из ТЧТовары Цикл
    Если СтрТовары.Номенклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Услуга Тогда
        Сообщить("Услуга: " + СтрТовары.Номенклатура);
    КонецЕсли;
КонецЦикла;

Выясним причину, почему конструкция СтрТовары.Номенклатура.ВидНоменклатуры является крайне неоптимальной. Когда мы обращаемся к реквизиту ссылки через точку, платформа выполняет следующие действия:

  1. Проверяет наличие объекта в кеше объектов на сервере (rphost).
  2. Если объекта в кеше нет, платформа выполняет неявный запрос SELECT * FROM Справочник.Номенклатура WHERE Ссылка = ....
  3. Важный момент: система считывает не только запрашиваемое поле ВидНоменклатуры, а всю запись целиком со всеми реквизитами (кроме табличных частей и хранилищ значений).
  4. Если в справочнике 100 реквизитов, вы прочитаете их все ради одного флажка. В цикле это превращается в лавинообразный рост нагрузки.

Неявное получение представления (преобразование в строку)

Посмотрим на строку Сообщить("Услуга: " + СтрТовары.Номенклатура);. Здесь нет явного обращения к реквизитам, но есть неявное преобразование типа СправочникСсылка в тип Строка. Рассмотрим, что происходит внутри системы:

Для вывода ссылки на экран платформа должна получить ее Представление. Это вызывает выполнение функции ПРЕДСТАВЛЕНИЕ() на уровне БД или обращение к модулю менеджера объекта (обработчик ОбработкаПолученияПредставления). Это полноценный запрос к базе данных. Если вы выводите сообщение для каждой строки из тысячи, вы получите тысячу лишних микро-запросов, каждый из которых требует времени на сетевой обмен между сервером приложений и СУБД.

Для оптимизации рекомендуется заменять автоматическое представление получением конкретного строкового поля в запросе, например, Наименование.

Работа с перечислениями и предопределенными данными

Многие задаются вопросом: является ли обращением к БД конструкция Перечисления.ВидыНоменклатуры.Услуга? Проанализируем механизмы кэширования:

Платформа 1С оптимизирует работу с метаданными. Ссылки на значения перечислений и идентификаторы предопределенных узлов кэшируются при запуске сеанса или первом обращении. Однако, существует разница в методах обращения:

Как правильно: использование запроса вместо точек

Вместо того чтобы «мучить» базу данных в цикле, мы должны подготовить все необходимые данные одним пакетом. Рассмотрим правильный подход:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТЧ.Номенклатура.Наименование КАК НоменклатураНаименование,
    |	ТЧ.Номенклатура КАК Ссылка
    |ИЗ
    |	Документ.ЗаказКлиента.Товары КАК ТЧ
    |ГДЕ
    |	ТЧ.Ссылка = &Ссылка
    |	И ТЧ.Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)";

Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить("Услуга: " + Выборка.НоменклатураНаименование);
КонецЦикла;

В данном примере мы используем ЛЕВОЕ СОЕДИНЕНИЕ (которое платформа делает под капотом при обращении через точку в тексте запроса) и получаем только нужные нам поля. Это выполняется одним обращением к СУБД, что в сотни раз быстрее работы в цикле.

Влияние RLS (Rights Level Security)

Разберем еще один скрытый аспект. Если в вашей базе настроены ограничения прав доступа на уровне записей (RLS), то каждое обращение через точку в коде заставляет систему проверять права доступа к целевому объекту. В запросе RLS применяется один раз ко всему набору данных, а в цикле — для каждой итерации. Это критически важный фактор для высоконагруженных систем.

Итоги и рекомендации

Проанализировав ситуацию, мы можем выделить основные правила «гигиены» кода в 1С:

  1. Избегайте «точек» от ссылок в циклах. Если вам нужен реквизит объекта внутри цикла — получите его заранее через запрос или выгрузите в ТаблицуЗначений с нужными колонками.
  2. Контролируйте преобразование типов. Конкатенация строки и ссылки ("Текст" + Ссылка) — это скрытый запрос представления.
  3. Используйте кэширование. Если вам все же нужно обращаться к свойствам объектов, делайте это через специализированные функции в привилегированных модулях с повторным использованием значений, чтобы снизить количество физических чтений из БД.
  4. Замер производительности. Всегда проверяйте свой код через встроенный «Замер производительности». Если вы видите, что строка с Сообщить или простым условием Если занимает значительный процент времени — ищите неявный запрос.

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

← На главную