Как ускорить передачу большой таблицы значений с сервера на клиент в 1С?

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

При разработке сложных аналитических рабочих мест в управляемом приложении разработчики часто сталкиваются с ситуацией, когда серверный запрос выполняется быстро, однако возврат управления на клиент занимает несколько секунд. Разберем типичный сценарий: на сервере заполняется реквизит формы типа ДанныеФормыКоллекция (таблица из 5 500 строк и 30 колонок). От момента завершения серверного метода до передачи контроля в клиентский код проходит 5–6 секунд. Проанализируем физику этого процесса и рассмотрим эффективные варианты решения проблемы.

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

  1. Вычисление дельты изменений и сериализация. При вызове контекстной процедуры &НаСервере платформа сравнивает состояние контекста до и после вызова. Если коллекция перезаполнена целиком, измененной считается каждая ячейка. При 5 500 строках и 30 колонках это 165 000 элементов данных. Сервер упаковывает их в подробный XML-пакет с описанием типов.
  2. Сетевой трафик. Нежатый XML-пакет для такого объема данных может занимать от 15 до 25 МБ. Передача крупного блока данных по сети создает задержку на уровне TCP-сокетов.
  3. Десериализация и создание объектов на клиенте. Клиентское приложение должно разобрать XML и создать в оперативной памяти 5 500 экземпляров объектов типа ДанныеФормыЭлементКоллекции, а затем перерисовать таблицу в визуальном интерфейсе. Это блокирует пользовательский поток.

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

Способ 1. Постраничная загрузка через временное хранилище (пейджинг)

Вместо того чтобы держать в реквизитах формы все 5 500 строк, организуем постраничный вывод (например, порциями по 50–100 строк). Вся таблица формируется в неконтекстном вызове, кэшируется во временном хранилище, а в интерфейс передается только текущая страница.

Разберем реализацию этого механизма по шагам:

  1. На сервере без контекста получаем полную таблицу и помещаем ее во временное хранилище, привязывая к уникальному идентификатору формы, чтобы платформа автоматически очистила память при закрытии окна.
  2. Выбираем только порцию строк для текущей страницы и возвращаем ее на клиент.
  3. На форме размещаем кнопки «Вперед», «Назад» и отображение номера страницы.

Посмотрим на пример кода серверных методов:


&НаСервереБезКонтекста
Функция СформироватьИСохранитьДанные(УникальныйИдентификаторФормы, АдресХранилища = "")
    Таблица = ПолучитьПолнуюТаблицуДанных(); // Формирование исходной таблицы значений
    Возврат ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификаторФормы);
КонецФункции

&НаСервере
Процедура ЗагрузитьСтраницуНаСервере(АдресХранилища, НомерСтраницы, РазмерСтраницы = 100)
    ТаблицаИзХранилища = ПолучитьИзВременногоХранилища(АдресХранилища);
    Если ТаблицаИзХранилища = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Очищаем текущие данные формы
    ТаблицаФормы.Очистить();
    
    ИндексНачала = (НомерСтраницы - 1) * РазмерСтраницы;
    ИндексКонца = Мин(ИндексНачала + РазмерСтраницы - 1, ТаблицаИзХранилища.Количество() - 1);
    
    Для Индекс = ИндексНачала По ИндексКонца Цикл
        ЗаполнитьЗначенияСвойств(ТаблицаФормы.Добавить(), ТаблицаИзХранилища[Индекс]);
    КонецЦикла;
КонецПроцедуры

При таком подходе на клиент передается всего 100 строк, что занимает менее 0.1 секунды.

Способ 2. Использование динамического списка

Главное достоинство объекта ДинамическийСписок заключается в том, что он по умолчанию считывает и передает на клиент только видимую область строк плюс небольшой запас для плавного скроллинга. Полная таблица из 5 500 строк не передается в клиентскую память целиком ни при каких условиях.

Если данные собираются сложным составным запросом, который нельзя уместить в один запрос динамического списка, хорошим решением является промежуточная запись результата в специализированный РегистрСведений с привязкой к сеансу или пользователю. После записи динамический список мгновенно отображает первые 30–40 строк, а прокрутка работает плавно и быстро.

Способ 3. Отображение через табличный документ

Если список предназначен преимущественно для просмотра и выбора, проанализируем замену таблицы формы на ТабличныйДокумент. В тонком клиенте механизм табличного документа оптимизирован: отображение виртуализировано, и ячейки подгружаются по мере прокрутки экрана. Это избавляет систему от необходимости создавать тысячи тяжелых объектов типа ДанныеФормыЭлементКоллекции.

Способ 4. Минимизация состава колонок и ссылочных данных

Если интерфейс требует наличия всех строк в едином списке, снизим объем XML-пакета за счет структуры данных:

  1. Исключение ссылок. Передача ссылочных типов (СправочникСсылка, ДокументСсылка) требует передачи метаданных ссылок. Замените их на строковые представления (Строка) там, где не требуется открытие формы объекта по нажатию.
  2. Удаление технических колонок. Служебные идентификаторы, ключи строк и флаги расчета не должны находиться в реквизитах формы. Храните соответствие ключей во временном хранилище на сервере. Сокращение числа колонок с 30 до 10 уменьшает объем пакета в 3 раза.
  3. Использование сжатия. При работе через веб-сервер (IIS или Apache) убедитесь, что включено сжатие (Gzip/Deflate) для трафика между сервером и клиентом. Это уменьшает время передачи XML-пакета по сети в несколько раз.
← На главную