При проектировании сложных запросов в системе «1С:Предприятие 8» разработчики постоянно используют временные таблицы. Они позволяют разбивать тяжелые выборки на логические шаги, упрощают чтение кода и помогают оптимизатору СУБД построить наиболее эффективный план выполнения. Однако в процессе разработки часто возникает вопрос: нужно ли в конце пакета запросов явно вызывать инструкцию УНИЧТОЖИТЬ для созданных временных таблиц? Насколько сильно это влияет на производительность и потребление ресурсов сервера?
В этой статье мы подробно проанализируем, как устроена работа с временными таблицами «под капотом» платформы 1С и СУБД, рассмотрим жизненный цикл этих объектов и выясним, в каких случаях явное удаление жизненно необходимо, а в каких — избыточно и даже вредно.
Для начала разберем физическую сущность временных таблиц. Когда мы пишем в запросе конструкцию ПОМЕСТИТЬ ИмяТаблицы, платформа 1С отправляет СУБД команду на создание реальной физической таблицы в специализированном системном хранилище:
tempdb. Временные таблицы создаются там под уникальными именами, чтобы избежать конфликтов между сеансами разных пользователей.pg_temp), которые изолированы в рамках конкретного подключения (сеанса).При заполнении временной таблицы данными СУБД выделяет под нее страницы памяти и дискового пространства. Объем этих ресурсов напрямую зависит от размера помещаемой таблицы. Если таблица содержит сотни тысяч или миллионы записей, нагрузка на дисковую подсистему и оперативную память сервера СУБД возрастает лавинообразно.
Давайте посмотрим на классический пример создания и явного удаления временной таблицы в тексте запроса:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Номенклатура.Код КАК Код
ПОМЕСТИТЬ ВТ_Товары
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Услуга = ЛОЖЬ;
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Товары.Товар,
ВТ_Товары.Код
ИЗ
ВТ_Товары КАК ВТ_Товары;
;
////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ВТ_Товары
Разберем детально, что происходит при выполнении этого пакета. Платформа сначала создает таблицу в СУБД, заполняет ее, затем выбирает данные для конечного результата и, наконец, выполняет команду удаления. Но как именно СУБД реагирует на команду УНИЧТОЖИТЬ?
На уровне СУБД команда платформы УНИЧТОЖИТЬ транслируется в инструкции удаления объектов (такие как DROP TABLE или TRUNCATE TABLE). Сама по себе эта операция в СУБД выполняется крайне быстро — за считанные миллисекунды. СУБД просто делает пометку в своих системных таблицах (метаданных), что данные страницы памяти и диска теперь свободны и могут быть использованы повторно.
Однако в высоконагруженных системах с тысячами активных пользователей этот процесс может столкнуться со следующими проблемами:
tempdb начинает испытывать перегрузку. Возникают ожидания типа PAGELATCH, когда разные потоки пытаются одновременно изменить структуру метаданных системной базы. В таких ситуациях операция удаления таблицы может «подвиснуть» на несколько секунд, парализуя работу смежных запросов. Для борьбы с этим в современных версиях MS SQL Server (начиная с 2019 года) рекомендуется включать режим оптимизации метаданных MEMORY_OPTIMIZED TEMPDB_METADATA.fasttrun, которое выполняет усечение таблиц через функцию fasttruncate() без изменения системных каталогов. Это позволяет PostgreSQL уничтожать временные таблицы практически мгновенно и без лишних блокировок.Выясним, когда временная таблица уничтожается автоматически, если мы НЕ пишем команду УНИЧТОЖИТЬ. Здесь ключевую роль играет то, как именно мы работаем с объектами платформы в коде на встроенном языке.
Рассмотрим простейший вызов запроса без явного создания менеджера временных таблиц:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Значение КАК Поле
|ПОМЕСТИТЬ ВТ_Данные;
|//... дальнейшая работа с ВТ
|ВЫБРАТЬ * ИЗ ВТ_Данные";
Результат = Запрос.Выполнить();
В этом сценарии время жизни временной таблицы ВТ_Данные жестко ограничено временем выполнения самого запроса. Как только метод Выполнить() завершает свою работу и управление возвращается в код 1С, платформа автоматически посылает в СУБД команду на уничтожение всех созданных в пакете временных таблиц. Писать здесь явное УНИЧТОЖИТЬ в конце пакета не имеет никакого практического смысла — платформа сделает это сама за ту же долю секунды.
Ситуация кардинально меняется, когда мы задействуем Менеджер временных таблиц для передачи данных между разными запросами:
МВТ = Новый МенеджерВременныхТаблиц;
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МВТ;
Запрос1.Текст =
"ВЫБРАТЬ Ссылка ПОМЕСТИТЬ ВТ_Товары ИЗ Справочник.Номенклатура";
Запрос1.Выполнить();
// ... Здесь может быть сложный программный код, расчеты, вызовы других процедур
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МВТ;
Запрос2.Текст =
"ВЫБРАТЬ * ИЗ ВТ_Товары ГДЕ ...";
Результат = Запрос2.Выполнить();
В данном случае временная таблица ВТ_Товары будет жить в СУБД до тех пор, пока жив сам объект МВТ (переменная МВТ находится в области видимости).
Если этот менеджер передан как параметр в глобальный модуль или удерживается в реквизитах какой-либо долгоживущей формы, данные в СУБД будут продолжать занимать место в tempdb и оперативной памяти сервера.
Проанализируем последствия длительного удержания МВТ без очистки:
tempdb, что может привести к переполнению диска СУБД.МенеджерВременныхТаблиц) временные таблицы могут оставаться активными до полного перезапуска сеанса пользователя.Именно в сценариях с долгоживущими менеджерами временных таблиц команда УНИЧТОЖИТЬ становится мощным инструментом оптимизации. Как только таблица выполнила свою роль и более не понадобится в последующих запросах этого менеджера, ее следует незамедлительно удалить.
Рассмотрим еще один важный архитектурный нюанс платформы «1С:Предприятие» — кэширование и повторное использование структур таблиц.
Если в рамках одного сеанса СУБД повторно выполняется запрос, создающий временную таблицу с точно такой же структурой колонок и типов данных, платформа 1С пытается оптимизировать этот процесс. Вместо того чтобы полностью удалять старую таблицу и создавать новую с нуля (что требует дополнительных ресурсов СУБД на работу с метаданными), платформа может просто очистить существующую структуру (выполнить легкий TRUNCATE) и заполнить ее новыми данными.
Если разработчик везде принудительно расставляет команду УНИЧТОЖИТЬ, он лишает платформу и СУБД возможности использовать этот механизм переиспользования. СУБД вынуждена раз за разом проходить через полноценные транзакционные циклы создания и удаления физических объектов в базе данных.
Обратим внимание на практическую сторону разработки. Многие программисты сталкиваются с тем, что использование явного удаления временных таблиц существенно усложняет процесс поиска ошибок в коде:
УНИЧТОЖИТЬ ВТ_Имя, консоль выдаст ошибку или просто покажет пустой результат на этом шаге, так как к моменту вывода данных таблица уже физически стерта. Разработчику приходится вручную комментировать строки удаления, чтобы проанализировать промежуточные результаты.В крупных тиражных решениях фирмы 1С (таких как ERP, ЗУП, Комплексная автоматизация) правила работы с временными таблицами жестко регламентированы. В коде БСП активно используются специализированные программные методы очистки.
Например, в коде часто можно встретить конструкции вызова процедур общего назначения, которые программно формируют запросы на удаление таблиц:
// Пример использования механизмов БСП для удаления временных таблиц
МассивТаблицДляУдаления = Новый Массив;
МассивТаблицДляУдаления.Добавить("ВТ_ЗаказыПокупателей");
МассивТаблицДляУдаления.Добавить("ВТ_ОстаткиТоваров");
ЗарплатаКадры.УничтожитьВТ(МассивТаблицДляУдаления, МВТ);
Такой подход позволяет централизованно управлять памятью, избегать ручного написания лишних строк УНИЧТОЖИТЬ в теле основных запросов и гарантирует своевременную очистку ресурсов сервера при работе со сложными транзитными выборками.
Подводя итог нашему анализу, сформулируем четкие и практичные правила для разработчиков.
Выполнить().tempdb.tempdb.Таким образом, явное удаление временных таблиц в 1С — это не просто дань «хорошим манерам» программирования, а важный инструмент осознанного управления ресурсами сервера. Применяйте его взвешенно, исходя из архитектуры вашего конкретного алгоритма, объемов обрабатываемых данных и времени жизни объектов в памяти.