В практике разработки на платформе 1С:Предприятие 8.3 часто возникает вопрос о так называемых «неявных» или «черных» запросах. Это ситуации, когда в коде нет явного использования объекта Запрос, но система все равно обращается к базе данных (SQL серверу) для получения данных. Если такие обращения происходят внутри цикла, производительность системы может упасть в десятки и сотни раз. Рассмотрим подробнее, какие конструкции кода вызывают скрытые обращения к БД и как правильно организовать работу с данными.
Разберем классический пример, который часто встречается в коде начинающих разработчиков. Проанализируем ситуацию, когда мы обходим табличную часть документа и хотим проверить вид номенклатуры:
Для каждого СтрТовары Из ТЧТовары Цикл
Если СтрТовары.Номенклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Услуга Тогда
Сообщить("Услуга: " + СтрТовары.Номенклатура);
КонецЕсли;
КонецЦикла;
Выясним причину, почему конструкция СтрТовары.Номенклатура.ВидНоменклатуры является крайне неоптимальной. Когда мы обращаемся к реквизиту ссылки через точку, платформа выполняет следующие действия:
SELECT * FROM Справочник.Номенклатура WHERE Ссылка = ....ВидНоменклатуры, а всю запись целиком со всеми реквизитами (кроме табличных частей и хранилищ значений).Посмотрим на строку Сообщить("Услуга: " + СтрТовары.Номенклатура);. Здесь нет явного обращения к реквизитам, но есть неявное преобразование типа СправочникСсылка в тип Строка. Рассмотрим, что происходит внутри системы:
Для вывода ссылки на экран платформа должна получить ее Представление. Это вызывает выполнение функции ПРЕДСТАВЛЕНИЕ() на уровне БД или обращение к модулю менеджера объекта (обработчик ОбработкаПолученияПредставления). Это полноценный запрос к базе данных. Если вы выводите сообщение для каждой строки из тысячи, вы получите тысячу лишних микро-запросов, каждый из которых требует времени на сетевой обмен между сервером приложений и СУБД.
Для оптимизации рекомендуется заменять автоматическое представление получением конкретного строкового поля в запросе, например, Наименование.
Многие задаются вопросом: является ли обращением к БД конструкция Перечисления.ВидыНоменклатуры.Услуга? Проанализируем механизмы кэширования:
Платформа 1С оптимизирует работу с метаданными. Ссылки на значения перечислений и идентификаторы предопределенных узлов кэшируются при запуске сеанса или первом обращении. Однако, существует разница в методах обращения:
ПредопределенноеЗначение("Перечисление.ВидыНоменклатуры.Услуга") — считается наиболее быстрым методом, так как значение кэшируется на этапе компиляции кода.Перечисления.ВидыНоменклатуры.Услуга — также эффективно и обычно не вызывает повторных запросов к SQL в каждой итерации цикла после первичного обращения.Вместо того чтобы «мучить» базу данных в цикле, мы должны подготовить все необходимые данные одним пакетом. Рассмотрим правильный подход:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧ.Номенклатура.Наименование КАК НоменклатураНаименование,
| ТЧ.Номенклатура КАК Ссылка
|ИЗ
| Документ.ЗаказКлиента.Товары КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &Ссылка
| И ТЧ.Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Услуга: " + Выборка.НоменклатураНаименование);
КонецЦикла;
В данном примере мы используем ЛЕВОЕ СОЕДИНЕНИЕ (которое платформа делает под капотом при обращении через точку в тексте запроса) и получаем только нужные нам поля. Это выполняется одним обращением к СУБД, что в сотни раз быстрее работы в цикле.
Разберем еще один скрытый аспект. Если в вашей базе настроены ограничения прав доступа на уровне записей (RLS), то каждое обращение через точку в коде заставляет систему проверять права доступа к целевому объекту. В запросе RLS применяется один раз ко всему набору данных, а в цикле — для каждой итерации. Это критически важный фактор для высоконагруженных систем.
Проанализировав ситуацию, мы можем выделить основные правила «гигиены» кода в 1С:
ТаблицуЗначений с нужными колонками."Текст" + Ссылка) — это скрытый запрос представления.Сообщить или простым условием Если занимает значительный процент времени — ищите неявный запрос.Соблюдение этих правил позволит вашим конфигурациям работать быстро даже на очень больших объемах данных, сохраняя отзывчивость интерфейса для конечного пользователя.