Разберем распространенную ситуацию в управляемом приложении 1С: при выполнении контекстного вызова серверной процедуры пользователь сталкивается со значительной задержкой (например, в несколько секунд). При этом замер производительности показывает, что задержка происходит на вызове сервера, однако внутри самой серверной процедуры ни одна строчка BSL-кода не занимает существенного времени — везде отображается около 0% времени выполнения.
Проанализируем причины такого поведения платформы 1С и рассмотрим по шагам методы оптимизации, которые позволяют полностью устранить эту проблему.
Штатный инструмент замера производительности 1С фиксирует только время работы кода на встроенном языке (BSL). Однако при динамическом изменении свойства ТекстЗапроса или параметров динамического списка основные временные затраты происходят вне BSL-кода:
ТекстЗапроса, платформа аннулирует внутренний кэш и схему динамического списка. Парсинг нового текста, проверка синтаксиса, определение ключевых полей и построение структуры данных происходят во внутреннем коде платформы. В замере BSL этот процесс выглядит как отсутствие нагрузки по строкам.&НаСервере) передает на сервер и обратно на клиент весь контекст формы, включая текущие структуры данных и реквизиты. Если контекст велик, расходы на сериализацию и десериализацию данных также вносят свой вклад в задержку.Если цель контекстного вызова заключалась лишь в фильтрации данных списка по датам или другим условиям, правильным решением будет отказаться от вызова сервера. Библиотека Стандартных Подсистем (БСП) предоставляет механизмы для установки параметров и отборов динамического списка прямо на клиенте.
Рассмотрим пример кода, в котором отбор по периоду устанавливается на клиенте без обращения к серверу:
// Установка отбора по началу и концу периода на клиенте через БСП
КомпоновкаДанныхКлиентСервер.ДобавитьОтбор(
Список.Отбор,
"ДатаПлатежа",
Неделя.ДатаНачала,
ВидСравненияКомпоновкиДанных.БольшеИлиРавно
);
КомпоновкаДанныхКлиентСервер.ДобавитьОтбор(
Список.Отбор,
"ДатаПлатежа",
Неделя.ДатаОкончания,
ВидСравненияКомпоновкиДанных.МеньшеИлиРавно,
,
,
Ложь
);
Установка отборов через методы КомпоновкаДанныхКлиентСервер или работу с КомпоновщикНастроек непосредственно на клиенте позволяет избежать вызова сервера, сохраняя структуру динамического списка и не выгружая кэш схемы.
В случаях, когда условия выборки должны быть гибкими, не следует переписывать свойство ТекстЗапроса полностью. Любое изменение текста запроса ведет к полному сбросу скомпилированной схемы динамического списка.
Посмотрим, как правильно заложить необязательные условия прямо в текст запроса с помощью фигурных скобок СКД:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
Документ.Дата КАК Дата,
Документ.СуммаДокумента КАК СуммаДокумента
ИЗ
Документ.Оплата КАК Документ
{ГДЕ
Документ.Дата >= &ДатаНачала,
Документ.Дата <= &ДатаОкончания}
При таком подходе текст запроса динамического списка остается неизменным. Платформа 1С самостоятельно подключает или отключает секцию ГДЕ при установке соответствующего параметра или отбора, не пересобирая схему с нуля.
Если для вычисления значений параметров динамического списка требуется сложная бизнес-логика, которую невозможно выполнить на клиенте, следует отделить расчет параметров от работы с формой:
&НаСервереБезКонтекста.Рассмотрим пример реализации такого подхода:
&НаКлиенте
Процедура ОбновитьДинамическийСписок()
// Получаем необходимые расчетные данные с сервера без передачи контекста формы
ПараметрыПериода = ПолучитьРассчитанныйПериодНаСервере(Объект.Организация);
// Устанавливаем параметры списка на клиенте
КомпоновкаДанныхКлиентСервер.УстановитьПараметр(
Список,
"НачалоПериода",
ПараметрыПериода.ДатаНачала
);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьРассчитанныйПериодНаСервере(Знач Организация)
Результат = Новый Структура("ДатаНачала", НачалоДня(ТекущаяДата()));
// Выполнение серверной логики...
Возврат Результат;
КонецФункция
Проанализируем основные правила работы с динамическими списками, соблюдение которых предотвращает проседания производительности:
ОсновнаяТаблица для динамического списка (если запрос строится к конкретной таблице). Это позволяет платформе выполнять считывание данных порциями и оптимизировать обращения к СУБД.ВидКлючаДинамическогоСписка и ключевые поля, чтобы платформа не отключала режим порционной выборки.ТекстЗапроса и ОсновнаяТаблица в самом начале, до обращения к Отбор или Параметры. Это предотвратит повторную инициализацию списка.