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

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

Для чего нужны временные таблицы в 1С

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

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

Главная практическая ценность временных таблиц — производительность и читаемость. Вместо одного гигантского запроса с множеством вложенных подзапросов разработчик получает цепочку простых шагов, каждый из которых легко отладить в консоли запросов. Кроме того, СУБД часто выполняет такой пакет быстрее, потому что промежуточный результат материализуется один раз и переиспользуется, а не вычисляется заново в каждом соединении.

Типичная ситуация, где временные таблицы незаменимы, — отчёты на СКД и обработки, где сначала нужно отобрать узкое подмножество данных (например, документы за период по отбору пользователя), а потом многократно обращаться к нему при расчёте оборотов, остатков и взаиморасчётов. Без временных таблиц такой отчёт либо работает медленно, либо превращается в неподдерживаемый запрос на сотни строк.

Что такое временная таблица и как она работает

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

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

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

Основные задачи, которые решают временные таблицы

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

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

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

Подзапрос используется 2+ разаКандидат на ПОМЕСТИТЬ

Посчитайте, сколько раз один и тот же подзапрос встречается в тексте

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

Проверьте, передаются ли в запрос данные, которых нет в базе

Отчёт медленно работаетВозможна оптимизация через ВТ

Замерьте время и посмотрите план запроса на предмет повторных вычислений

Запрос нечитаемРазбейте на шаги

Более 2–3 уровней вложенности — признак того, что пора выносить в ВТ

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

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

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

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

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

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

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

Влияние на производительность: когда ускорение, а когда наоборот

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

Однако временные таблицы — не бесплатны. Материализация требует памяти и места во временном табличном пространстве СУБД. Если поместить во временную таблицу очень большой набор данных, который потом используется один раз, можно получить замедление вместо ускорения: сервер потратит ресурсы на запись и чтение промежуточных данных.

Маршрут решения

Помещать в ВТ или оставить подзапрос

Подзапрос используется два и более разВыносите во временную таблицу — выигрыш почти гарантирован
Подзапрос возвращает мало строк после жёсткого отбораВременная таблица уместна: дальнейшие соединения будут дешёвыми
Подзапрос используется один раз и возвращает много данныхОставьте вложенный запрос или виртуальную таблицу — материализация не окупится
Нужно соединить данные из кода с данными базыТолько временная таблица через параметр-таблицу значений

Практический способ проверить эффект — замерить время выполнения до и после изменения на реальных объёмах, а в клиент-серверном варианте дополнительно посмотреть план запроса на стороне СУБД. Оптимизировать «на глаз» по тексту запроса ненадёжно: поведение оптимизатора зависит от статистики и объёмов конкретной базы.

Типичные ошибки при работе с временными таблицами

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

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

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

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

Временные таблицы против альтернатив

Чем заменить временную таблицу

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

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

Виртуальная таблица регистра

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

Таблица значений с обходом в коде

Гибче для экзотической логики, но соединения с данными базы в цикле — классический источник запросов в цикле и падения производительности

Пакетный запрос без ПОМЕСТИТЬ

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

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

Антипаттерн, который стоит распознавать, — выгрузка данных в таблицу значений с последующим перебором строк и запросами внутри цикла. Это почти всегда медленнее, чем один запрос с временной таблицей, и создаёт лишнюю нагрузку на сервер. Признак такого кода: вызов Выполнить() внутри Для Каждого.

Контроль результата и ограничения

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

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

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

Доступность таблицы
Норма

Второй запрос пакета выполняется без ошибок

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

Ошибка «Таблица не найдена» — проверьте менеджер ВТ

Число строк во ВТ
Норма

Соответствует ожидаемому отбору

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

Строк на порядки больше — отбор не сработал или потерян

Время выполнения
Норма

Пакет быстрее исходного варианта или сопоставим

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

Стало медленнее — таблица слишком велика или используется один раз

Итоговые данные
Норма

Совпадают с контрольным расчётом

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

Расхождения — проверяйте типы соединений и дубли в ВТ

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

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

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

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

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

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

Жёсткого ограничения по количеству нет — упор идёт в память и временное пространство СУБД. На практике пакеты из 5–15 временных таблиц встречаются в сложных отчётах и работают нормально. Если таблиц становится больше, стоит проверять, не пора ли уничтожать отработанные таблицы оператором УНИЧТОЖИТЬ.

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

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

Нужно ли явно уничтожать временные таблицы?

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

Работают ли временные таблицы в СКД?

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

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

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

Итог

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

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