Разработка и Конфигурация · 12 мин
Зачем нужны временные таблицы в 1С и как их правильно использовать
Зачем нужны временные таблицы в 1С: менеджер временных таблиц, пакетные запросы, типичные ошибки, примеры кода и способы проверить результат.
Временная таблица в 1С — это промежуточный набор данных, который запрос создаёт внутри сеанса и использует в последующих запросах пакета. Она существует только в рамках менеджера временных таблиц и исчезает после его уничтожения, не засоряя базу данных. Механизм критичен для производительности: вместо многократного обращения к тяжёлым таблицам регистров вы один раз отбираете нужные данные и дальше работаете уже с компактной выборкой.
Без временных таблиц разработчик вынужден либо строить громоздкие вложенные запросы, которые СУБД оптимизирует плохо, либо выгружать данные в таблицы значений и обрабатывать их в циклах на сервере приложений. Оба подхода проигрывают: первый — по скорости и читаемости, второй — по объёму передаваемых данных и нагрузке на память. Временные таблицы снимают эту дилемму, позволяя разбить сложную логику на прозрачные этапы.
Механизм доступен во всех современных конфигурациях на управляемых и обычных формах, работает и в файловом, и в клиент-серверном варианте. Ниже разобраны практические сценарии, код, ограничения и типичные ошибки.
Что такое временная таблица и менеджер временных таблиц
Временная таблица создаётся конструкцией ПОМЕСТИТЬ ИмяТаблицы в тексте запроса. Физически она хранится на стороне СУБД (в tempdb для MS SQL Server) или в памяти файловой базы, но недоступна другим сеансам и другим запросам вне своего менеджера.
Менеджер временных таблиц — объект МенеджерВременныхТаблиц, который связывает несколько запросов в единый контекст. Пока менеджер жив, все запросы, у которых он установлен в свойстве МенеджерВременныхТаблиц, видят одни и те же временные таблицы. После выхода переменной менеджера из области видимости или явного вызова Закрыть() таблицы уничтожаются.
Важно понимать: временная таблица — не объект метаданных. Её нельзя описать в конфигураторе, она не попадает в резервную копию и не требует прав на изменение данных. Это чисто вычислительный инструмент.
Ключевые сценарии применения
Ускорение сложных отчётов
Типовая ситуация: отчёт по продажам обращается к регистру накопления с миллионами записей, а пользователь отбирает данные за месяц по одной организации. Если фильтр применять в каждом виртуальном обращении и соединении, СУБД будет повторно сканировать большие диапазоны. Решение — первым запросом пакета поместить во временную таблицу уже отфильтрованные движения, а все последующие выборки строить по ней.
Передача списка значений в запрос
Когда нужно отобрать документы по списку контрагентов, полученному из другого запроса или из таблицы значений, временная таблица заменяет неуклюжие конструкции с параметром-массивом и условием В (&Список). Вы помещаете таблицу значений через параметр запроса, индексируете её и соединяете с основными данными — это работает быстрее и корректнее по типам.
Многоэтапные расчёты в проведении
В процедуре ОбработкаПроведения часто требуется: получить остатки, рассчитать себестоимость, распределить суммы, сформировать движения. Каждый этап удобно оформлять отдельным запросом пакета, где промежуточные результаты живут во временных таблицах. Такой код легче отлаживать: любой промежуточный этап можно выгрузить и посмотреть.
Поместите выборку во временную таблицу один раз
Вынесите подзапрос в ПОМЕСТИТЬ
Сначала отбор во временную таблицу, потом соединения
Временная таблица не нужна — лишний шаг
Как создать и использовать: рабочий пример
Минимальный рабочий шаблон выглядит так: создаётся менеджер, назначается запросу, выполняется пакет из нескольких текстов, разделённых точкой с запятой.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура,
| СУММА(Продажи.Количество) КАК Количество
|ПОМЕСТИТЬ ВТ_Продажи
|ИЗ
| РегистрНакопления.Продажи КАК Продажи
|ГДЕ
| Продажи.Период МЕЖДУ &Начало И &Конец
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура
|;
|ВЫБРАТЬ
| ВТ.Номенклатура,
| ВТ.Количество,
| Цены.Цена
|ИЗ
| ВТ_Продажи КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(&Конец) КАК Цены
| ПО ВТ.Номенклатура = Цены.Номенклатура";
Результат = Запрос.Выполнить().Выгрузить();
Обратите внимание на предложение ИНДЕКСИРОВАТЬ ПО. Для временных таблиц платформа не строит индексы автоматически, и соединение по неиндексированному полю на большом объёме превращается в полное сканирование. Индексируйте поля, по которым будете соединять таблицу дальше.
- 1Создайте объект МенеджерВременныхТаблиц
- 2Назначьте его запросу через свойство МенеджерВременныхТаблиц
- 3Первым запросом пакета поместите отфильтрованные данные (ПОМЕСТИТЬ)
- 4Добавьте ИНДЕКСИРОВАТЬ ПО по полям соединений
- 5Выполняйте последующие запросы пакета, ссылаясь на временную таблицу по имени
- 6Проверьте промежуточный результат через ВЫБРАТЬ * ИЗ ВТ_Имя при отладке
Временные таблицы против альтернатив
Не каждая задача требует временной таблицы. Сопоставление основных подходов помогает выбрать осознанно.
| Подход | Когда подходит | Ограничения |
|---|---|---|
| Временная таблица | Многоэтапные запросы, повторное использование выборки | Живёт только внутри менеджера, требует индексации вручную |
| Вложенный запрос | Простая одноуровневая логика, один запрос | Плохо читается и оптимизируется при глубокой вложенности |
| Таблица значений | Обработка в коде, произвольные вычисления, вывод на форму | Данные перекачиваются с СУБД целиком, нет соединений на стороне СУБД |
| Параметр-массив в условии В | Небольшой список значений-фильтров | Медленно на больших списках, проблемы с составными типами |
Что выбрать
Данные нужны в нескольких запросах пакета; большой исходный объём, который надо один раз сузить
Логика простая, выборка используется один раз, читаемость не страдает
Нужна программная обработка строк, выгрузка на клиент или заполнение табличной части
Типичные ошибки и ограничения
Первая распространённая ошибка — помещение во временную таблицу избыточных данных. Если выбрать «на всякий случай» все поля регистра без фильтра, временная таблица раздувается, запись в tempdb становится отдельной тяжёлой операцией и весь выигрыш теряется. Помещайте только те поля и строки, которые реально нужны на следующих этапах.
Вторая ошибка — обращение к временной таблице из запроса, которому не назначен тот же менеджер. Платформа выдаст ошибку «Таблица не найдена». То же произойдёт, если менеджер уже уничтожен: например, он был локальной переменной функции, а запрос выполняется после её завершения.
Третья группа проблем — виртуальные таблицы регистров внутри временных. Конструкция вида ПОМЕСТИТЬ ... ИЗ РегистрНакопления.Остатки.Остатки() без параметров виртуальной таблицы заставит СУБД построить срез по всем измерениям. Всегда передавайте период и условия в параметры виртуальной таблицы — это многократно уменьшает объём вычислений.
Как проверить результат и отладить пакет
Главное преимущество поэтапного подхода — отлаживаемость. Чтобы посмотреть содержимое временной таблицы, достаточно выполнить отдельным запросом с тем же менеджером текст ВЫБРАТЬ * ИЗ ВТ_Продажи и выгрузить результат в таблицу значений. В консоли запросов с поддержкой временных таблиц это делается одной кнопкой.
Для оценки эффекта используйте технологический журнал с событием DBMSSQL (или аналог для вашей СУБД): сравните длительность запроса до и после внедрения временной таблицы. Признак правильной оптимизации — сокращение числа логических чтений и устранение повторных обращений к большим таблицам в плане запроса.
Как проверить результат
Строки соответствуют заданному фильтру, полей ровно столько, сколько нужно
Лишние колонки, строки вне периода, дубли
Суммарное время меньше, чем у исходного монолитного запроса
Пакет медленнее — вероятно, избыточный объём во временной таблице
Соединения по временной таблице используют индекс
Полное сканирование временной таблицы при соединениях
Если пакет стал медленнее после введения временных таблиц, проверьте три вещи: объём помещаемых данных, наличие индексов и количество обращений — если временная таблица читается лишь один раз, она, скорее всего, не нужна.
Границы применения и безопасная практика
Временные таблицы не заменяют правильную архитектуру запроса. Если вы помещаете в них данные, чтобы потом обойти результат в цикле и дозапросить по каждой строке — это антипаттерн «запрос в цикле», который временные таблицы не лечат. Данные следует обрабатывать множественными операциями, а не построчно.
В клиент-серверном варианте помните о нагрузке на tempdb: несколько одновременно работающих тяжёлых отчётов с большими временными таблицами могут исчерпать дисковое пространство tempdb. Согласуйте с администратором СУБД размер и размещение tempdb, если отчёты массовые.
Что важно запомнить
Временные таблицы нужны для многоэтапной обработки данных внутри пакета запросов: один раз отобрать, проиндексировать и многократно использовать. Помещайте минимум полей и строк, всегда задавайте параметры виртуальным таблицам, проверяйте результат выборкой из временной таблицы и замером времени.
Частые вопросы
Чем временная таблица отличается от таблицы значений?
Временная таблица живёт на стороне СУБД и участвует в запросах — её можно соединять, группировать, фильтровать средствами SQL. Таблица значений — объект встроенного языка в памяти сервера приложений: её удобно обходить в коде и показывать пользователю, но соединять с данными базы напрямую нельзя, только через помещение в запрос.
Как передать таблицу значений во временную таблицу?
Передайте таблицу значений как параметр запроса и в первом запросе пакета выполните ВЫБРАТЬ Т.Поле1, Т.Поле2 ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК Т. Не забудьте проиндексировать поля, по которым планируете соединения.
Когда удаляются временные таблицы?
Автоматически — при уничтожении менеджера временных таблиц (выход переменной из области видимости и сборка мусора) или при завершении сеанса. Явно можно вызвать метод Закрыть() у менеджера либо выполнить в пакете запрос УНИЧТОЖИТЬ ИмяТаблицы, если таблица больше не нужна в середине работы.
Почему запрос выдаёт ошибку «Таблица не найдена»?
Чаще всего запросу не назначен тот менеджер временных таблиц, в котором создана таблица, либо менеджер уже уничтожен. Проверьте, что все запросы пакета используют один экземпляр МенеджерВременныхТаблиц, а сам объект объявлен в области видимости, переживающей выполнение запроса.
Нужно ли индексировать временную таблицу всегда?
Нет. Индексация оправдана, если по таблице будут соединения или фильтрация по конкретным полям и объём данных заметный. Для маленькой таблицы, читаемой один раз целиком, индекс — лишняя работа для СУБД.
Можно ли использовать временные таблицы в СКД?
Да, через набор данных «запрос» с пакетным текстом либо программно, передав в компоновку готовый менеджер временных таблиц. В типовых отчётах часто применяют связку: программно готовится менеджер с временными таблицами, затем он подключается к процессору компоновки данных.