Как работает "ПолучитьИзВременногоХранилища" и как правильно хранить данные между серверными вызовами?

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

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

Задача: сохранение данных на сервере

Рассмотрим ситуацию: у нас есть несколько ТаблицаЗначений объемом по несколько тысяч строк. Они формируются один раз и используются в дальнейшем. Основной инструмент для этого в 1С — функции работы с временным хранилищем. Подобный механизм часто применяется в прикладных задачах, например, когда выполняется тестирование запросов к Ветис с сохранением параметров в хранилище.

Встают закономерные вопросы:

  1. Насколько ресурсоемкой является операция чтения из хранилища?
  2. Как физически хранятся эти данные?
  3. Как лучше организовать хранение: помещать каждую таблицу отдельно или упаковать их все в одну Структуру?

Механизм работы временного хранилища

Для начала разберем базовый алгоритм использования. Мы не храним сами данные на клиенте, мы храним только адрес (строку-ссылку), по которому эти данные лежат на сервере.

Типовой паттерн работы выглядит следующим образом:

  1. На сервере вычисляем данные.
  2. Помещаем их во временное хранилище, привязывая к уникальному идентификатору формы (чтобы данные жили, пока открыта форма).
  3. Возвращаем адрес хранилища на клиент и сохраняем его в реквизит формы.
  4. При следующих вызовах передаем адрес с клиента на сервер и получаем данные обратно.

Посмотрим на пример реализации кода:


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

КонецФункции

// Серверная процедура для работы с данными
&НаСервере
Процедура ОбработатьДанныеПоКнопке(Адрес)
    
    // Получаем данные обратно
    // В этот момент происходит десериализация
    Данные = ПолучитьИзВременногоХранилища(Адрес);
    
    // Работаем с копией данных
    Данные.ТЗ1.Свернуть("Колонка1", "Колонка2"); 
    
    // ВАЖНО: Если мы изменили данные и хотим сохранить изменения
    // для следующих вызовов, их нужно поместить обратно!
    // Если этого не сделать, в хранилище останется старая версия.
    ПоместитьВоВременноеХранилище(Данные, Адрес);

КонецПроцедуры

// Клиентский код
&НаКлиенте
Процедура КомандаРасчет(Команда)
    // Сохраняем адрес в реквизит формы (строка)
    АдресХранилища = РасчитатьИПоместитьДанныеНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура КомандаОбработка(Команда)
    ОбработатьДанныеПоКнопке(АдресХранилища);
КонецПроцедуры

Что происходит "под капотом"?

Давайте проанализируем, что физически происходит при вызове ПолучитьИзВременногоХранилища и почему это может влиять на производительность.

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

2. Цена операции "Получить"
Операция ПолучитьИзВременногоХранилища выполняет обратный процесс — десериализацию. Система читает байты и восстанавливает из них объект (например, ТаблицаЗначений) в памяти текущего серверного процесса. Именно процесс сериализации/десериализации является основным потребителем ресурсов CPU. Чтение с диска (если данные ушли в своп) также добавляет задержки.

3. Кэширование
В платформе существует оптимизация. Данные могут кэшироваться в памяти рабочего процесса (rphost). Однако при выполнении тяжелых операций в несколько потоков, когда задействован конвейер обработки задач, данные могут перемещаться между процессами, и нагрузка на сервис сеансовых данных возрастает.

Стратегия хранения: Структура или отдельные таблицы?

Разберем один из ключевых вопросов: как лучше хранить несколько таблиц?

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

Вариант Б: Отдельные адреса для каждой ТЗ
Вы помещаете каждую таблицу отдельно и храните на клиенте структуру адресов или несколько реквизитов формы: АдресТЗ1, АдресТЗ2. Плюсы: Вы получаете из хранилища только то, что нужно в конкретной процедуре. Минусы: Чуть сложнее управлять адресами.

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

Важные нюансы и "подводные камни"

1. Изменяемость данных
Частая ошибка начинающих: изменение полученной таблицы без помещения обратно. Функция ПолучитьИзВременногоХранилища возвращает копию данных. Если вы изменили таблицу (удалили строки, свернули), в хранилище останется старая версия. Чтобы сохранить изменения, нужно снова вызвать ПоместитьВоВременноеХранилище по тому же адресу.

2. Время жизни данных
Если вы привязали данные к УникальныйИдентификатор формы, они очистятся автоматически при закрытии формы. Однако, если данные используются для длительных вычислений, лучше задействовать фоновые задания с отслеживанием результата выполнения без БСП, чтобы не блокировать интерфейс и иметь возможность получить результат по адресу хранилища после завершения задачи.

3. Альтернатива: Регистр сведений
Если объем данных исчисляется сотнями тысяч строк, или требуется сложная выборка (соединения, фильтры как в запросах), временное хранилище — не лучший выбор. В таких случаях целесообразнее использовать временный (или служебный) Регистр сведений. В регистр добавляется измерение КлючСессии (GUID), и данные пишутся туда. Преимущества регистра:

Итоги

  1. Для 2-5 тысяч строк использование ПолучитьИзВременногоХранилища вполне оправдано и работает быстро.
  2. Физически это сериализованные данные, управляемые кластером серверов.
  3. Трудоемкость зависит от объема данных (время уходит на десериализацию).
  4. Если таблицы используются независимо — храните их под разными адресами.
  5. Не забывайте помещать данные обратно, если вы их модифицировали в серверном методе.
← На главную