Как ускорить открытие формы с подчиненным динамическим списком в 1С?

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

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

Почему подчиненный динамический список замедляет открытие формы

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

  1. Безусловная серверная инициализация. Свойство Видимость управляет только отображением элементов на стороне клиента. На сервере при вызове события ПриСозданииНаСервере платформа в любом случае инициализирует схему динамического списка, подготавливает внутренние структуры данных и выполняет первичный запрос к базе данных для получения первой страницы строк.
  2. Особенности запросов к табличным частям. Для динамического списка с источником в виде табличной части документа (например, Документ.ЗаказКлиента.Товары) невозможно указать свойство ОсновнаяТаблица. Из-за этого отключается механизм динамического считывания порциями по кластерному индексу, а СУБД выполняет запрос как для произвольной неиндексированной выборки.
  3. Влияние механизма RLS. В типовых конфигурациях (таких как УТ 11, ERP, КА) ко всем запросам динамических списков автоматически подключаются шаблоны ограничения доступа на уровне записей. Проверка прав для двух списков одновременно существенно увеличивает время работы серверного контекста.

Способ 1. Подмена текста запроса на заглушку при инициализации

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

При создании формы на сервере заменим сложный запрос динамического списка на минимальный, а боевой текст запроса сохраним или восстановим только в момент включения видимости:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Если по умолчанию панель состава выключена, отключаем тяжелый запрос
    Если Не Элементы.ГруппаСоставЗаказа.Видимость Тогда
        СписокТовары.ТекстЗапроса = "ВЫБРАТЬ 1 КАК Поле";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ФлагПоказыватьСоставПриИзменении(Элемент)
    Элементы.ГруппаСоставЗаказа.Видимость = ФлагПоказыватьСостав;
    ВключитьОтображениеСоставаНаСервере(ФлагПоказыватьСостав);
КонецПроцедуры

&НаСервере
Процедура ВключитьОтображениеСоставаНаСервере(Включить)
    Если Включить Тогда
        СписокТовары.ТекстЗапроса = 
            "ВЫБРАТЬ
            |	ЗаказТовары.Номенклатура КАК Номенклатура,
            |	ЗаказТовары.Количество КАК Количество,
            |	ЗаказТовары.ВариантОбеспечения КАК ВариантОбеспечения
            |ИЗ
            |	Документ.ЗаказКлиента.Товары КАК ЗаказТовары
            |ГДЕ
            |	ЗаказТовары.Ссылка = &ТекЗаказ";
        
        // Устанавливаем актуальный параметр текущей строки
        ТекущиеДанные = Элементы.СписокЗаказы.ТекущиеДанные;
        ТекСсылка = ?(ТекущиеДанные <> Неопределено, ТекущиеДанные.Ссылка, ПредопределенноеЗначение("Документ.ЗаказКлиента.ПустаяСсылка"));
        СписокТовары.Параметры.УстановитьЗначениеПараметра("ТекЗаказ", ТекСсылка);
    Иначе
        СписокТовары.ТекстЗапроса = "ВЫБРАТЬ 1 КАК Поле";
    КонецЕсли;
КонецПроцедуры

Способ 2. Замена динамического списка на таблицу формы с обработчиком ожидания

Для отображения подчиненных строк документа использование второго динамического списка часто оказывается избыточным. Более эффективное архитектурное решение — использовать обычную таблицу формы (коллекцию ТаблицаЗначений или ДанныеФормыКоллекция), которая заполняется по требованию.

Чтобы избежать многократных серверных вызовов, когда пользователь быстро перемещается по основному списку с зажатой клавишей со стрелкой, обязательно реализуем развязку через клиентский таймер (debounce):


&НаКлиенте
Процедура СписокЗаказыПриАктивизацииСтроки(Элемент)
    // Перезапускаем однократный таймер с задержкой 0.1-0.2 секунды
    ОтключитьОбработчикОжидания("ОбновитьСоставТекущегоЗаказа");
    ПодключитьОбработчикОжидания("ОбновитьСоставТекущегоЗаказа", 0.15, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьСоставТекущегоЗаказа()
    ТекущиеДанные = Элементы.СписокЗаказы.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Или Не Элементы.ГруппаСоставЗаказа.Видимость Тогда
        ТоварыТекущегоЗаказа.Очистить();
        Возврат;
    КонецЕсли;
    
    ЗаполнитьСоставНаСервере(ТекущиеДанные.Ссылка);
КонецПроцедуры

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

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

Способ 3. Оптимизация структуры запроса и выбор источника данных

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

  1. Чтение из регистров накопления. В типовых конфигурациях данные о вариантах обеспечения и фактических резервах фиксируются в специализированных регистрах (например, РегистрНакопления.ОбеспечениеЗаказов или РегистрНакопления.ЗаказыКлиентов). Чтение срезов или оборотов из индексированных таблиц регистров по конкретному заказу выполняется быстрее, чем сканирование строк документа.
  2. Использование стандартных отборов вместо жестких параметров в запросе. Если вы сохраняете динамический список, избегайте жестких условий ГДЕ Таблица.Ссылка = &ТекЗаказ внутри текста запроса. Рекомендуется настраивать отбор через Список.КомпоновщикНастроек.Настройки.Отбор. Когда список неактивен, элемент отбора можно программно отключать (Использование = Ложь), что позволяет оптимизатору платформы эффективнее кэшировать планы выполнения запросов.

Способ 4. Динамическое управление свойством «ПутьКДанным»

Еще один способ ускорить инициализацию — отключить привязку таблицы формы к источнику на этапе создания. Если у элемента таблицы формы свойство ПутьКДанным не заполнено, платформа не опрашивает динамический список при открытии формы.

При включении видимости пользователем мы программно устанавливаем связь:


&НаСервере
Процедура ПереключитьСвязьТаблицы(Включить)
    Если Включить Тогда
        Элементы.ТаблицаТовары.ПутьКДанным = "СписокТовары";
    Иначе
        Элементы.ТаблицаТовары.ПутьКДанным = "";
    КонецЕсли;
КонецПроцедуры

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

← На главную