К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как работает менеджер временных таблиц в 1С

Как работает МенеджерВременныхТаблиц в 1С: создание, помещение результатов запроса, жизненный цикл таблиц, типичные ошибки и примеры кода для разработчика.

Менеджер временных таблиц — объект встроенного языка 1С, который управляет временными таблицами, создаваемыми запросами в рамках одного сеанса работы с базой данных. Временная таблица — это материализованный результат запроса, хранящийся в базе данных (в служебных таблицах SQL-сервера или в файловой базе) и доступный последующим запросам. Главная ценность механизма — возможность разбить сложную выборку на этапы и многократно переиспользовать промежуточные результаты без повторного сканирования основных таблиц.

Без менеджера временные таблицы живут только внутри одного запроса: конструкция «ПОМЕСТИТЬ ВТ_Товары» в одном запросе недоступна другому запросу, если у них нет общего менеджера. Как только вы создаёте объект МенеджерВременныхТаблиц и назначаете его нескольким запросам через свойство Запрос.МенеджерВременныхТаблиц, все таблицы, помещённые этими запросами, становятся общими и доступны до явного уничтожения или до уничтожения самого менеджера.

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

Что такое временная таблица и зачем нужен менеджер

Временная таблица в 1С — это не таблица значений в памяти и не виртуальная таблица регистра. Это физически материализованный набор строк, который платформа создаёт на стороне СУБД (в клиент-серверном режиме — во временных таблицах SQL-сервера, в файловом — в служебных структурах базы). Она существует вне контекста конкретного запроса и может читаться другими запросами, у которых тот же менеджер.

Менеджер временных таблиц выполняет роль контейнера и диспетчера: он регистрирует созданные таблицы, позволяет получить их список методом ПолучитьТаблицы(), выгрузить содержимое любой таблицы в таблицу значений для отладки и контролирует их время жизни. Пока существует хотя бы одна ссылка на менеджер, его таблицы доступны; когда менеджер уничтожается (например, при выходе из процедуры, где он объявлен локально), все его таблицы удаляются.

Базовый цикл: создать менеджер, поместить таблицу, прочитать её

Минимальный рабочий шаблон состоит из четырёх шагов: создать менеджер, выполнить запрос с инструкцией ПОМЕСТИТЬ, назначить тот же менеджер следующему запросу, прочитать временную таблицу в нём как обычный источник данных. Ключевой момент — менеджер назначается до выполнения запроса, а не после.

bsl
МенеджерВТ = Новый МенеджерВременныхТаблиц;

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка КАК Документ,
| Док.Контрагент КАК Контрагент
|ПОМЕСТИТЬ ВТ_Документы
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ
| Док.Дата МЕЖДУ &Начало И &Конец
| И Док.Проведен";
Запрос.УстановитьПараметр("Начало", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Конец", КонецМесяца(ТекущаяДатаСеанса()));
Запрос.Выполнить();

Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст =
"ВЫБРАТЬ
| ВТ.Контрагент КАК Контрагент,
| КОЛИЧЕСТВО(ВТ.Документ) КАК ЧислоДокументов
|ИЗ
| ВТ_Документы КАК ВТ
|СГРУППИРОВАТЬ ПО
| ВТ.Контрагент";
Результат = Запрос2.Выполнить().Выгрузить();

Обратите внимание: первый запрос вызывается методом Выполнить() без обработки результата — его задача только материализовать таблицу. Второй запрос обращается к ВТ_Документы как к обычной таблице в предложении ИЗ. Если бы у второго запроса не было того же менеджера, платформа выдала бы ошибку «Таблица не найдена».

Порядок работы с менеджером
  1. 1
    Создайте объект: МенеджерВТ = Новый МенеджерВременныхТаблиц
  2. 2
    Назначьте его запросу до вызова Выполнить()
  3. 3
    В тексте запроса используйте ПОМЕСТИТЬ ИмяТаблицы
  4. 4
    Следующим запросам назначайте тот же менеджер и читайте таблицу по имени
  5. 5
    Ненужные таблицы удаляйте запросом УНИЧТОЖИТЬ ИмяТаблицы
  6. 6
    Проверьте результат через МенеджерВТ.Таблицы и выгрузку в таблицу значений

Жизненный цикл и уничтожение временных таблиц

Временная таблица существует, пока существует её менеджер. Если менеджер объявлен локальной переменной в процедуре, таблицы удаляются при выходе из неё. Если менеджер хранится в реквизите формы или модуля объекта — таблицы живут дольше, что бывает полезно при многоэтапных расчётах, но требует аккуратности с памятью и блокировками на стороне СУБД.

Удалить отдельную таблицу досрочно можно запросом с инструкцией УНИЧТОЖИТЬ ВТ_Документы, выполненным на том же менеджере. Это стоит делать, когда таблица больше не нужна, а менеджер будет жить ещё долго: в клиент-серверном режиме большие временные таблицы занимают ресурсы tempdb на SQL Server, и их своевременная очистка снижает нагрузку.

Повторное помещение таблицы с тем же именем без уничтожения приведёт к ошибке «Таблица уже существует». Поэтому в циклах и повторно вызываемых процедурах перед ПОМЕСТИТЬ либо выполняют УНИЧТОЖИТЬ, либо используют уникальные имена.

Как менеджер работает с пакетными запросами

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

Метод ВыполнитьПакет() возвращает массив результатов: для запросов с ПОМЕСТИТЬ элемент массива содержит результат с количеством помещённых записей, для итогового запроса — выборку. Это удобно для проверки: промежуточные результаты показывают, сколько строк попало в каждую временную таблицу, и позволяют быстро локализовать этап, где данные «потерялись» из-за слишком жёсткого отбора.

Производительность: индексы и объём данных

Когда временная таблица соединяется с большими таблицами, важно проиндексировать поля соединения. В языке запросов для этого служит конструкция ИНДЕКСИРОВАТЬ ПО Поле1, Поле2 после инструкции ПОМЕСТИТЬ. Без индекса СУБД может выполнять полное сканирование временной таблицы при каждом соединении, что на больших объёмах резко замедляет выполнение.

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

Отладка: как посмотреть содержимое временной таблицы

Содержимое любой временной таблицы можно выгрузить в таблицу значений и посмотреть в отладчике. Для этого создаётся запрос с тем же менеджером и текстом вида «ВЫБРАТЬ * ИЗ ВТ_Документы», либо используется коллекция МенеджерВТ.Таблицы: у каждого элемента есть свойства Имя и метод ПолучитьДанные() (в новых версиях платформы — Выгрузить() через запрос).

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

bsl
// Выгрузка временной таблицы для просмотра в отладчике
ЗапросОтладки = Новый Запрос;
ЗапросОтладки.МенеджерВременныхТаблиц = МенеджерВТ;
ЗапросОтладки.Текст = "ВЫБРАТЬ * ИЗ ВТ_Документы";
ТЗ = ЗапросОтладки.Выполнить().Выгрузить();

Типичные ошибки при работе с менеджером

Типичные ошибки
01
Запрос без назначенного менеджера обращается к временной таблице — ошибка «Таблица не найдена». Назначайте МенеджерВременныхТаблиц каждому запросу, который читает ВТ.
02
Повторное ПОМЕСТИТЬ в таблицу с тем же именем без УНИЧТОЖИТЬ — ошибка «Таблица уже существует». Уничтожайте таблицу или используйте уникальные имена.
03
Соединение временной таблицы без ИНДЕКСИРОВАТЬ ПО по полям связи — медленные запросы на больших объёмах.
04
Помещение в ВТ лишних полей и строк — перерасход памяти и tempdb. Отбирайте минимум данных.
05
Использование результата Выполнить() у запроса с ПОМЕСТИТЬ как будто это выборка — там только количество записей, данных нет.

Ещё одна тонкая ошибка — попытка передать менеджер между серверными вызовами или между клиентом и сервером. Менеджер временных таблиц не сериализуется: он существует только в контексте того вызова, где создан. Если расчёт разбит на несколько серверных процедур, менеджер нужно передавать как параметр в пределах одного серверного вызова, а не хранить «между» вызовами.

Когда менеджер временных таблиц не нужен

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

Альтернатива для разовых задач — вложенные запросы и виртуальные таблицы. Но при многократном обращении к одному и тому же отфильтрованному набору данных временная таблица почти всегда выигрывает: СУБД материализует её один раз, а не вычисляет заново при каждом обращении.

Сравнение подходов

Менеджер временных таблиц

Несколько независимых запросов, отладка промежуточных данных, обмен ВТ между процедурами. Требует контроля времени жизни.

Пакетный запрос без менеджера

Одна цепочка вычислений в одном тексте запроса. Проще, но нельзя посмотреть ВТ между этапами из кода.

Вложенные запросы

Разовая фильтрация без повторного использования. Неудобны при многократном обращении к тем же данным.

FAQ

Чем временная таблица отличается от таблицы значений?

Временная таблица живёт на стороне СУБД и доступна только запросам с общим менеджером; таблица значений — объект в памяти сервера 1С, с которым работают встроенным языком. ВТ эффективнее для соединений с большими данными, ТЗ удобнее для программной обработки небольших наборов.

Можно ли использовать один менеджер для запросов в разных процедурах?

Да, если менеджер передан как параметр или хранится в доступном обеим процедурам месте в пределах одного серверного вызова. Между отдельными серверными вызовами передать его нельзя — объект не сериализуется.

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

Через свойство МенеджерВТ.Таблицы — это коллекция описаний таблиц, у каждого элемента есть свойство Имя. В отладчике эту коллекцию можно развернуть и посмотреть состав.

Что произойдёт, если не уничтожать временные таблицы?

Они будут удалены автоматически при уничтожении менеджера. Проблема возникает только при долгоживущем менеджере: таблицы накапливаются и расходуют ресурсы СУБД, поэтому в длительных расчётах ненужные ВТ стоит удалять командой УНИЧТОЖИТЬ.

Почему запрос ругается «Таблица уже существует»?

Значит, в этом менеджере уже есть таблица с таким именем — например, процедура вызвана повторно. Перед ПОМЕСТИТЬ выполните запрос УНИЧТОЖИТЬ ИмяТаблицы или генерируйте уникальные имена.

Нужно ли индексировать каждую временную таблицу?

Нет. Индексируйте только таблицы, которые соединяются с большими источниками, и только по полям соединения или отбора. Для маленьких ВТ на десятки строк индекс не даёт выигрыша.

Итог

Что важно запомнить

МенеджерВременныхТаблиц связывает несколько запросов общими временными таблицами: назначайте его каждому запросу до выполнения, помещайте данные через ПОМЕСТИТЬ, индексируйте поля соединений, удаляйте ненужные таблицы командой УНИЧТОЖИТЬ и не храните менеджер дольше, чем требует расчёт.