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