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

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

Менеджер временных таблиц в 1С: что это и как с ним работать

Менеджер временных таблиц в 1С: назначение, создание, передача между запросами и пакетами, типичные ошибки и приёмы отладки временных таблиц.

Менеджер временных таблиц — это объект встроенного языка 1С (тип МенеджерВременныхТаблиц), который хранит временные таблицы, созданные запросами, и позволяет использовать их повторно в других запросах в рамках одного сеанса работы. Без менеджера каждая временная таблица, созданная конструкцией ПОМЕСТИТЬ, существует только внутри одного пакетного запроса и уничтожается после его выполнения.

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

Механизм доступен и в тонком, и в толстом клиенте, и на сервере, причём временные таблицы физически размещаются во временной базе данных СУБД (tempdb в MS SQL Server, пространство временных таблиц в PostgreSQL). Понимание того, где живут эти таблицы и когда они удаляются, помогает избегать утечек ресурсов и неожиданного роста нагрузки на сервер СУБД.

Зачем нужен менеджер временных таблиц

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

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

Кроме того, менеджер позволяет передавать данные между запросами программно: один запрос готовит таблицу «ВТ_Контрагенты», следующий использует её для отбора, третий — для итогового отчёта. Это стандартный приём в типовых конфигурациях и в схемах компоновки данных с набором данных «Запрос».

Как создать и назначить менеджер запросу

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

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

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = МВТ;

Запрос.Текст =

"ВЫБРАТЬ

| Реализация.Контрагент КАК Контрагент,

| СУММА(Реализация.Сумма) КАК Сумма

|ПОМЕСТИТЬ ВТ_Продажи

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Проведен

|СГРУППИРОВАТЬ ПО

| Реализация.Контрагент

|ИНДЕКСИРОВАТЬ ПО

| Контрагент";

Запрос.Выполнить();

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

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

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

Чтение и проверка временных таблиц

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

Если МВТ.Таблицы.Найти("ВТ_Продажи") <> Неопределено Тогда

ЗапросПроверки = Новый Запрос("ВЫБРАТЬ * ИЗ ВТ_Продажи");

ЗапросПроверки.МенеджерВременныхТаблиц = МВТ;

Результат = ЗапросПроверки.Выполнить().Выгрузить();

КонецЕсли;

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

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

Контрольные точки

Как проверить результат

Таблица создана
Норма

МВТ.Таблицы.Найти("ИмяТаблицы") возвращает описание таблицы

Тревожный признак

Метод возвращает Неопределено — запрос с ПОМЕСТИТЬ не выполнялся или использовал другой менеджер

Данные в таблице
Норма

Выгрузка через ВЫБРАТЬ * возвращает ожидаемые строки

Тревожный признак

Пустой результат — проверьте отборы и соединения в исходном запросе

Видимость между запросами
Норма

Второй запрос с тем же менеджером читает таблицу без ошибок

Тревожный признак

Ошибка «Таблица не найдена» — у запросов разные менеджеры временных таблиц

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

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

Для явного удаления используется конструкция УНИЧТОЖИТЬ в тексте запроса:

Запрос.Текст = "УНИЧТОЖИТЬ ВТ_Продажи";

Запрос.Выполнить();

Хорошая практика — уничтожать промежуточную таблицу сразу после того, как построена следующая, которая её заменяет. В пакетном запросе это делается отдельным пакетом через разделитель ;. Если менеджер больше не нужен целиком, достаточно обнулить переменную или вызвать метод Закрыть() — все его таблицы будут удалены.

Менеджер в пакетных запросах и СКД

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

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

Ещё один сценарий — передача таблицы значений во временную таблицу через параметр запроса: ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &Таблица КАК Таблица, где параметром передаётся таблица значений. Это удобно для отбора по списку значений, сформированному в коде, вместо длинного условия В (&Список).

Передача таблицы значений как параметра запроса с помещением во временную таблицу обычно работает быстрее и чище, чем условие В (&Список) с массивом из тысяч элементов, и не упирается в ограничения СУБД на длину списка параметров.
ПЗ
Практическое замечание

Типичные ошибки и ограничения

Самая частая ошибка — обращение к временной таблице из запроса, которому не назначен менеджер или назначен другой менеджер. Платформа выдаёт ошибку «Таблица не найдена», и причина не всегда очевидна, если запросы создаются в разных процедурах.

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

Также помните, что временные таблицы не видны между разными сеансами и даже между разными серверными вызовами, если менеджер не передан явно. Хранить там данные «про запас» между интерактивными действиями пользователя нельзя.

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

Когда менеджер не нужен: альтернативы

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

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

Сравнение вариантов

Временные таблицы через менеджер

Подходят для больших объёмов, многоэтапных выборок и повторного использования результата; требуют управления жизненным циклом

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

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

Таблица значений в памяти

Подходит для программной обработки и небольших объёмов; не поддерживает соединения средствами запроса без передачи обратно в запрос

Итог

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

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

Частые вопросы

Чем менеджер временных таблиц отличается от пакетного запроса?

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

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

Напрямую в окне вычисления выражения содержимое не отображается, но можно выполнить отдельный запрос «ВЫБРАТЬ * ИЗ ИмяТаблицы» с тем же менеджером и выгрузить результат в таблицу значений, которую уже можно просмотреть. Также существуют внешние инструменты и консоли запросов, показывающие временные таблицы пакета.

Что происходит с временными таблицами после завершения процедуры?

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

Почему запрос с временной таблицей работает медленно?

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

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

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

Как передать таблицу значений во временную таблицу запроса?

Передайте таблицу значений как параметр запроса и используйте конструкцию «ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ИЗ &Таблица КАК Таблица». Колонки таблицы значений станут полями временной таблицы. Убедитесь, что у колонок заданы типы, иначе платформа может неоптимально определить типы полей.