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

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

Зачем нужны временные таблицы в 1С и как их правильно использовать

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

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

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

Механизм доступен во всех современных конфигурациях на управляемых и обычных формах, работает и в файловом, и в клиент-серверном варианте. Ниже разобраны практические сценарии, код, ограничения и типичные ошибки.

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

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

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

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

Ключевые сценарии применения

Ускорение сложных отчётов

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

Передача списка значений в запрос

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

Многоэтапные расчёты в проведении

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

К одним данным обращаются 2+ разаПовторное чтение тяжёлой таблицы

Поместите выборку во временную таблицу один раз

Запрос содержит вложенные подзапросыСУБД плохо оптимизирует

Вынесите подзапрос в ПОМЕСТИТЬ

Нужно сузить большой регистрФильтр по периоду и измерениям

Сначала отбор во временную таблицу, потом соединения

Одноразовая простая выборкаОдин запрос без повторов

Временная таблица не нужна — лишний шаг

Как создать и использовать: рабочий пример

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

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

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

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

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.Количество) КАК Количество

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

|ИЗ

| РегистрНакопления.Продажи КАК Продажи

|ГДЕ

| Продажи.Период МЕЖДУ &Начало И &Конец

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

| Продажи.Номенклатура

|

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

| Номенклатура

|;

|ВЫБРАТЬ

| ВТ.Номенклатура,

| ВТ.Количество,

| Цены.Цена

|ИЗ

| ВТ_Продажи КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(&Конец) КАК Цены

| ПО ВТ.Номенклатура = Цены.Номенклатура";

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

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

Порядок работы с временными таблицами
  1. 1
    Создайте объект МенеджерВременныхТаблиц
  2. 2
    Назначьте его запросу через свойство МенеджерВременныхТаблиц
  3. 3
    Первым запросом пакета поместите отфильтрованные данные (ПОМЕСТИТЬ)
  4. 4
    Добавьте ИНДЕКСИРОВАТЬ ПО по полям соединений
  5. 5
    Выполняйте последующие запросы пакета, ссылаясь на временную таблицу по имени
  6. 6
    Проверьте промежуточный результат через ВЫБРАТЬ * ИЗ ВТ_Имя при отладке

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

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

ПодходКогда подходитОграничения
Временная таблицаМногоэтапные запросы, повторное использование выборкиЖивёт только внутри менеджера, требует индексации вручную
Вложенный запросПростая одноуровневая логика, один запросПлохо читается и оптимизируется при глубокой вложенности
Таблица значенийОбработка в коде, произвольные вычисления, вывод на формуДанные перекачиваются с СУБД целиком, нет соединений на стороне СУБД
Параметр-массив в условии ВНебольшой список значений-фильтровМедленно на больших списках, проблемы с составными типами

Что выбрать

Временная таблица

Данные нужны в нескольких запросах пакета; большой исходный объём, который надо один раз сузить

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

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

Таблица значений

Нужна программная обработка строк, выгрузка на клиент или заполнение табличной части

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

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

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

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

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

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

Главное преимущество поэтапного подхода — отлаживаемость. Чтобы посмотреть содержимое временной таблицы, достаточно выполнить отдельным запросом с тем же менеджером текст ВЫБРАТЬ * ИЗ ВТ_Продажи и выгрузить результат в таблицу значений. В консоли запросов с поддержкой временных таблиц это делается одной кнопкой.

Для оценки эффекта используйте технологический журнал с событием DBMSSQL (или аналог для вашей СУБД): сравните длительность запроса до и после внедрения временной таблицы. Признак правильной оптимизации — сокращение числа логических чтений и устранение повторных обращений к большим таблицам в плане запроса.

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

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

Содержимое временной таблицы
Норма

Строки соответствуют заданному фильтру, полей ровно столько, сколько нужно

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

Лишние колонки, строки вне периода, дубли

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

Суммарное время меньше, чем у исходного монолитного запроса

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

Пакет медленнее — вероятно, избыточный объём во временной таблице

План запроса на СУБД
Норма

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

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

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

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

Границы применения и безопасная практика

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

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

Итог

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

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

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

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

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

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

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

Когда удаляются временные таблицы?

Автоматически — при уничтожении менеджера временных таблиц (выход переменной из области видимости и сборка мусора) или при завершении сеанса. Явно можно вызвать метод Закрыть() у менеджера либо выполнить в пакете запрос УНИЧТОЖИТЬ ИмяТаблицы, если таблица больше не нужна в середине работы.

Почему запрос выдаёт ошибку «Таблица не найдена»?

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

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

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

Можно ли использовать временные таблицы в СКД?

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