Как сохранить менеджер временных таблиц между серверными вызовами?

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

Многие разработчики сталкиваются с задачей оптимизации работы с большими объемами данных в управляемых формах. Естественное желание — один раз выполнить тяжелый запрос, поместить результат во Временную таблицу (МВТ) и затем быстро фильтровать или группировать эти данные при каждом действии пользователя. Однако при попытке реализовать это «в лоб» мы сталкиваемся с тем, что МенеджерВременныхТаблиц не сохраняется между серверными вызовами.

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

Почему МенеджерВременныхТаблиц нельзя сохранить?

Важно понимать, что МенеджерВременныхТаблиц — это объект, работающий в рамках текущего контекста исполнения на сервере 1С. Когда выполняется серверный вызов, 1С открывает сессию с СУБД. Временные таблицы (#TemporaryTable) создаются на стороне SQL-сервера и существуют исключительно в рамках этой конкретной сессии. Как только серверный вызов завершается, 1С освобождает ресурсы, соединение возвращается в пул, а СУБД автоматически удаляет все временные таблицы. Сериализовать «живой» указатель на объект СУБД невозможно.

Решение 1: Использование РегистраСведений для временных данных

Если данные необходимо часто фильтровать и они занимают большой объем, самым надежным решением является использование физических таблиц в базе данных. Создайте специальный РегистрСведений (непериодический, независимый), который будет служить «буфером» для ваших промежуточных расчетов.

  1. Создайте структуру регистра с нужным количеством измерений и ресурсов, соответствующих полям вашей временной таблицы.
  2. Обязательно добавьте измерение, например, УникальныйИдентификаторСеанса (тип УникальныйИдентификатор), чтобы данные разных пользователей не перемешивались.
  3. При первом вызове записывайте результат тяжелого запроса в этот регистр.
  4. В последующих серверных вызовах делайте выборку уже из этого РегистраСведений с отбором по вашему идентификатору.

Этот метод позволяет полноценно использовать индексы СУБД, что обеспечивает высокую производительность даже при работе с миллионами строк.


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

Решение 2: Использование ВременногоХранилища

Если объем данных не критически велик (например, до нескольких десятков тысяч записей), мы можем воспользоваться механизмом ВременногоХранилища. В этом случае мы сериализуем таблицу в структуру или саму ТаблицуЗначений.

Рассмотрим порядок действий:

  1. Выполняем запрос и выгружаем результат в ТаблицуЗначений.
  2. Помещаем эту таблицу во ВременноеХранилище с помощью функции ПоместитьВоВременноеХранилище().
  3. Получаем Адрес (строку-ключ), которую передаем на клиент (в реквизит формы).
  4. При следующем серверном вызове передаем этот Адрес обратно, считываем данные из хранилища и при необходимости создаем новую временную таблицу в текущем МенеджереВременныхТаблиц.

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

Решение 3: Оптимизация архитектуры запроса

Часто проблема возникает из-за того, что мы пытаемся хранить данные «на будущее», вместо того чтобы пересчитать их оптимально. Проанализируем ситуацию: возможно, стоит пересмотреть структуру запроса, используя вложенные запросы или пакетные запросы. Современные СУБД очень эффективно работают с кэшированием планов запросов. Если вы построите запрос так, что он будет выполняться быстро с передачей параметров, необходимость в удержании МенеджераВременныхТаблиц может отпасть сама собой.

Чего делать не стоит

В ходе дискуссий часто предлагают использовать «вечные» фоновые задания с бесконечными циклами для удержания контекста сеанса. Мы настоятельно рекомендуем избегать такой практики. Это приводит к:

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

← На главную