Как эффективнее обрабатывать строки таблицы значений: на клиенте или на сервере?

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

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

Механизм подгрузки данных и правило 35 строк

Рассмотрим ситуацию, которая часто описывается в методической литературе (например, у М. Г. Хрусталевой): когда мы работаем с объектом типа ДанныеФормыКоллекция на клиенте, платформа не передает все строки сразу. Вместо этого передается только первая порция данных (обычно это 35 строк), а остальные подгружаются по мере необходимости.

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

Почему опытный путь не всегда подтверждает теорию?

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

  1. Объем данных и кэширование: Если серверная процедура заполнила таблицу и вернула управление на клиент, измененные данные передаются в составе общего пакета ответа сервера. Для небольших коллекций (до нескольких сотен или даже тысячи строк) платформа может принять решение передать данные целиком, если их объем невелик. В этом случае при последующем обходе на клиенте данные уже находятся в оперативной памяти клиента.
  2. Способ заполнения: Если таблица заполняется непосредственно в процедуре ПриСозданииНаСервере, то при первом обращении на клиенте данные могут подкачиваться порциями. Однако, если вы вызвали серверный метод из клиентского кода, заполнили там коллекцию и вернулись на клиент, платформа часто передает всю актуальную информацию сразу.
  3. Оптимизация платформы: Современные версии платформы 8.3 динамически рассчитывают размер порции. Число 35 является ориентировочным; фактическое количество зависит от разрешения экрана, высоты строк и настроек буферизации.

Разберем на примере: программный обход таблицы

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


&НаКлиенте
Процедура ИнвертироватьФлаги(Команда)
    
    // Прямой обход коллекции на клиенте
    Для Каждого СтрокаТЗ Из Объект.Товары Цикл
        СтрокаТЗ.Пометка = Истина;
    КонецЦикла;
    
КонецПроцедуры

Если в таблице Товары находится 10 000 строк, и они еще не были полностью прокручены пользователем, этот цикл вызовет серию серверных запросов (примерно по одному на каждые 30–50 строк). Это существенно замедлит выполнение задачи.

Работа с данными на сервере: контекстные и внеконтекстные вызовы

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

Вариант 1: Контекстный вызов (&НаСервере)

При вызове процедуры &НаСервере вся форма целиком (все ее реквизиты) сериализуется и отправляется на сервер. После обработки она возвращается обратно. Это "дорогой" процесс, если форма содержит много данных.

Вариант 2: Внеконтекстный вызов (&НаСервереБезКонтекста)

Этот метод наиболее эффективен для обработки больших таблиц. Мы передаем на сервер только саму таблицу, обрабатываем ее и возвращаем результат. Рассмотрим реализацию:


&НаКлиенте
Процедура ОбработатьНаСервереБезКонтекста(Команда)
    
    // Получаем таблицу из данных формы
    ТаблицаОбъект = Объект.Товары.Выгрузить();
    
    // Выполняем обработку
    ОбработатьТаблицуНаСервере(ТаблицаОбъект);
    
    // Загружаем данные обратно
    Объект.Товары.Загрузить(ТаблицаОбъект);
    
КонецПроцедуры

&НаСервереБезКонтекста
СтандартнаяПроцедура ОбработатьТаблицуНаСервере(ТаблицаЗначений)
    
    Для Каждого Стр Из ТаблицаЗначений Цикл
        Стр.Пометка = Истина;
    КонецЦикла;
    
КонецПроцедуры

В данном случае мы работаем на сервере не с типом ДанныеФормыКоллекция, а с полноценным объектом ТаблицаЗначений. Это работает в десятки раз быстрее, так как ТаблицаЗначений — это оптимизированная структура данных, а не прокси-объект интерфейса.

Важные нюансы: ссылки и примитивные типы

Проанализируем ситуацию, когда в колонках таблицы находятся не только Булево или Строка, но и ссылки на тяжелые объекты (Справочники, Документы). Если при обходе на клиенте вы обратитесь к свойству ссылки (например, Строка.Товар.Артикул), платформа выполнит отдельный неявный серверный вызов для получения этого значения. Это "убьет" производительность интерфейса даже при небольшом количестве строк.

Рекомендации по выбору места обработки:

Подведем итоги

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

  1. Механизм подгрузки строк существует и работает автоматически при обращении к индексу.
  2. Для гарантированно быстрой работы используйте &НаСервереБезКонтекста с выгрузкой/загрузкой коллекции.
  3. Избегайте обращений через точку к ссылочным полям внутри циклов на клиенте.
  4. Если ваша обработка в дальнейшем приведет к групповому изменению данных в базе, лучше сразу выполнять все проверки и изменения на стороне сервера в одной транзакции.

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

← На главную