Вопрос об использовании команды УНИЧТОЖИТЬ в текстах запросов 1С часто становится предметом споров среди разработчиков. С одной стороны, платформа 1С:Предприятие декларирует автоматическую очистку временных таблиц. С другой — на крупных проектах с большими объемами данных пренебрежение явным удалением объектов может привести к деградации производительности сервера СУБД и даже к аварийному завершению работы сеансов. В этой статье мы подробно разберем механизмы работы временных таблиц, проанализируем поведение СУБД и выясним, в каких случаях «уборка» за собой является обязательной.
Рассмотрим, что происходит, когда мы выполняем запрос с инструкцией ПОМЕСТИТЬ. На стороне СУБД (например, MS SQL Server) создается реальная таблица в системной базе данных tempdb. Если в запросе не используется МенеджерВременныхТаблиц, область видимости этих таблиц ограничена текущим запросом. Проанализируем действия платформы после завершения работы такого запроса: как показывает SQL-профайлер, 1С отправляет команду truncate table для всех созданных временных таблиц. Это означает, что данные удаляются, но сама структура таблицы может оставаться в кэше для повторного использования в рамках сессии.
Ситуация меняется, когда мы используем МенеджерВременныхТаблиц. В этом случае временные таблицы существуют до тех пор, пока объект менеджера не будет удален из памяти или пока не будет вызвана команда Закрыть(). Если в цикле или в длинной цепочке процедур мы создаем десятки таблиц и не уничтожаем их, они накапливаются, занимая ресурсы сервера.
Важно понимать, что временные таблицы нагружают не только дисковую подсистему, но и оперативную память сервера СУБД. Рассмотрим процесс кэширования: SQL Server старается держать страницы данных временных таблиц в Buffer Pool (оперативной памяти) для ускорения доступа. Если мы создаем огромную таблицу объемом в несколько гигабайт и не удаляем ее сразу после использования, она продолжает удерживать место в оперативной памяти, вытесняя оттуда полезные данные других таблиц (индексы, часто используемые записи). Это приводит к росту чтений с диска для других запросов и общему замедлению системы.
Проанализируем пример кода, где явное удаление оправдано:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура,
| СУММА(Продажи.Количество) КАК Кол
|ПОМЕСТИТЬ ВТ_Обороты
|ИЗ
| РегистрНакопления.Продажи КАК Продажи
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Обороты.Номенклатура,
| ВТ_Обороты.Кол,
| Цены.Цена
|ИЗ
| ВТ_Обороты КАК ВТ_Обороты
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
| ПО ВТ_Обороты.Номенклатура = Цены.Номенклатура;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТ_Обороты";
В данном примере, если ВТ_Обороты содержит сотни тысяч строк, команда УНИЧТОЖИТЬ в конце пакета позволит СУБД немедленно освободить ресурсы, не дожидаясь завершения всех внутренних процессов платформы по закрытию запроса. Для автоматизации этой задачи в сложных пакетах можно использовать инструмент для расстановки команд УНИЧТОЖИТЬ в пакетных запросах.
Одной из критических проблем является неконтролируемый рост файлов tempdb. Выясним причину этого явления: каждая операция вставки во временную таблицу фиксируется в логе транзакций tempdb. Если временные таблицы не удаляются, а запросы выполняются интенсивно, лог транзакций не может быть эффективно очищен, что приводит к заполнению всего дискового пространства. В практике встречаются случаи, когда tempdb разрастается до сотен гигабайт из-за нескольких неоптимальных запросов, которые не очищают за собой временные данные.
Практическая рекомендация: Если объем данных во временной таблице превышает 100 000 строк или 100 Мб, её стоит удалять явно. Это «золотое правило» помогает избежать внезапного исчерпания места на диске сервера СУБД.
Рассмотрим важный нюанс, связанный с использованием временных таблиц в динамических списках. Программисты иногда пытаются оптимизировать сложные списки, создавая временные таблицы в тексте запроса и добавляя в конце УНИЧТОЖИТЬ. Это приводит к фатальной ошибке платформы, часто с дампом памяти или текстом "Недопустимое состояние объекта [entext - src\Select.cpp]".
Разберем причину: динамический список считывает данные порциями (по мере прокрутки пользователем). Если вы уничтожаете таблицу в тексте запроса, то при попытке списка прочитать следующую порцию данных (следующие 20-30 строк) временной таблицы в СУБД уже не существует. Запомните: в запросах динамических списков использовать команду УНИЧТОЖИТЬ категорически нельзя.
Если ваша база работает под управлением PostgreSQL, вопрос удаления таблиц стоит еще острее. В этой СУБД создание временных таблиц может приводить к «раздуванию» (bloat) системного каталога pg_class. Если сессии пользователей долго не закрываются (например, в режиме обычного приложения), а временные таблицы создаются и не удаляются явно, это замедляет работу планировщика запросов. Явное УНИЧТОЖИТЬ помогает поддерживать системные таблицы метаданных СУБД в чистоте.
Для высоконагруженных систем (HighLoad) существует и обратная сторона медали. Посмотрим на ситуацию глубже: при очень частом (тысячи раз в секунду) создании и удалении мелких временных таблиц в MS SQL Server могут возникать задержки на системных страницах распределения пространства (PFS, GAM страницы). Если таблицы крошечные (несколько строк), иногда выгоднее позволить платформе удалить их пакетно в конце, чтобы не создавать лишнюю нагрузку на системные объекты tempdb постоянными командами DROP.
Проанализировав все за и против, мы можем сформулировать следующие рекомендации для разработчика 1С:
МенеджераВременныхТаблиц, если они больше не нужны по ходу алгоритма. Это критично для экономии памяти сервера приложений и СУБД.УНИЧТОЖИТЬ для больших объемов данных (более 100к строк), даже если менеджер не установлен. Это освобождает Buffer Pool СУБД и предотвращает разрастание tempdb.УНИЧТОЖИТЬ в динамических списках, чтобы не вызвать падение платформы.ИНДЕКСИРОВАТЬ ПО...), такая таблица становится «дороже» для сервера. Её удаление после использования должно быть приоритетным.Соблюдение этих правил не только повышает стабильность вашей системы, но и демонстрирует профессиональный подход к разработке («чистый код»), облегчая дальнейшую поддержку и оптимизацию конфигурации.