Как ускорить программное заполнение дерева значений на управляемой форме в 1С

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

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

Выясним причины низкой производительности

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

  1. Циклическое заполнение и вложенные выборки: Использование конструкций вида Выборка.Выбрать() и добавление каждой строки вручную через Строки.Добавить() на уровне встроенного языка 1С создает огромные накладные расходы при десятках тысяч итераций.
  2. Использование ссылочных типов в колонках: Если колонки дерева значений имеют тип СправочникСсылка или составной тип данных, платформа при передаче на клиент и отрисовке таблицы может выполнять неявные вызовы для получения строковых представлений данных. Кроме того, хранение ссылок существенно увеличивает объем сериализуемых данных.
  3. Большой объем контекста формы: Коллекция ДанныеФормыДерево при передаче между клиентом и сервером полностью сериализуется, что нагружает память и замедляет работу интерфейса.

Шаг 1. Формирование иерархии средствами языка запросов

Вместо обхода выборки во вложенных циклах построим готовую иерархическую структуру прямо в запросе при помощи секции ИТОГИ ПО. Это позволяет перенести группировку данных на сторону СУБД, что работает в десятки раз быстрее.

Посмотрим на пример формирования запроса с иерархией по номенклатуре и характеристикам:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК СсылкаНоменклатуры,
    |	Номенклатура.Наименование КАК Товар,
    |	Номенклатура.Артикул КАК Артикул,
    |	Номенклатура.Производитель.Наименование КАК Производитель,
    |	ХарактеристикиНоменклатуры.Ссылка КАК СсылкаХарактеристики,
    |	ХарактеристикиНоменклатуры.Наименование КАК Характеристика
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиНоменклатуры
    |		ПО ХарактеристикиНоменклатуры.Владелец = Номенклатура.Ссылка
    |ГДЕ
    |	НЕ Номенклатура.ЭтоГруппа
    |ИТОГИ ПО
    |	СсылкаНоменклатуры";

РезультатЗапроса = Запрос.Выполнить();

Шаг 2. Выгрузка результата запроса и передача в реквизит формы

Полученный результат запроса выгружается сразу в объект ДеревоЗначений с сохранением иерархии группировок, после чего помещается в реквизит формы методом ЗначениеВРеквизитФормы() или ЗначениеВДанныеФормы().

Рассмотрим, как выглядит этот компактный и быстрый код:


&НаСервере
Процедура ЗаполнитьДеревоНаСервере()
    
    // Получаем дерево значений напрямую из запроса
    ДеревоРезультат = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
    
    // Переносим данные в реквизит управляемой формы
    ЗначениеВРеквизитФормы(ДеревоРезультат, "ОбъектСпДерево");
    
КонецПроцедуры

Шаг 3. Исключение ссылочных типов и типизация колонок

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

  1. Замена ссылок на строки: В запросе получаем наименования (Номенклатура.Наименование) или строковые идентификаторы (УникальныйИдентификатор()), если требуется последующая идентификация объекта.
  2. Ограничение длины строк: Для строковых колонок дерева значений на форме следует указывать точную квалификацию (например, Строка(150) вместо неограниченной длины). Это уменьшает накладные расходы при сериализации.
  3. Устранение неявных запросов: При наличии только примитивных типов платформа отрисовывает дерево мгновенно, не пытаясь дочитывать данные объектов.

Шаг 4. Альтернативные варианты оптимизации интерфейса

Если объем данных превышает сотни тысяч записей, даже оптимизированное дерево может вызывать задержки при отрисовке на клиенте. В таких случаях разберем альтернативные архитектурные решения:

  1. Использование Динамического списка: Если структура данных позволяет, вместо дерева значений рекомендуется использовать элемент управления ДинамическийСписок. Он считывает данные порциями по мере прокрутки и практически не расходует память клиента.
  2. Ленивая загрузка дерева (Lazy Loading): При открытии формы в дерево загружаются только элементы верхнего уровня. Подчиненные узлы (характеристики, остатки, цены) считываются с сервера и добавляются в конкретную ветку только в момент раскрытия или активизации строки пользователем.
  3. Живой поиск с отложенным вызовом: Для организации поиска по дереву без зависания интерфейса обработчик события поля ввода ИзменениеТекстаРедактирования связывают с механизмом ПодключитьОбработчикОжидания() с небольшой задержкой (например, 0.3-0.5 секунды), выполняя поиск через &НаСервереБезКонтекста.
← На главную