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