При работе с платформой 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда выполнение, казалось бы, обычного запроса приводит к резкому сокращению свободного места на системном диске С. Особенно остро эта проблема проявляется при передаче в запрос ТаблицыЗначений в качестве параметра. Рассмотрим подробнее, почему это происходит, как механизмы 1С взаимодействуют с СУБД и что нужно сделать, чтобы память не «съедалась».
Прежде всего, нам необходимо понять, что происходит «под капотом» системы, когда мы используем метод УстановитьПараметр для передачи таблицы значений. В этот момент платформа не просто читает данные из памяти, она инициирует создание физической временной таблицы в хранилище СУБД.
Если мы работаем в клиент-серверном варианте, данные выгружаются в системную базу tempdb (для MS SQL Server) или в аналогичные структуры других СУБД (например, PostgreSQL). В файловом же режиме создаются временные файлы формата v8_..._tmp в каталоге временных файлов пользователя (%TEMP%). Поскольку этот каталог по умолчанию находится на диске C, мы наблюдаем его стремительное заполнение.
Проанализируем фрагмент кода, который стал причиной проблемы. В тексте запроса автора содержалась следующая конструкция:
|ИЗ
| ВТ1 КАК ВТ1,
| ВТ2 КАК ВТ2
В этом месте кроется критическая ошибка. Перечисление таблиц через запятую в секции ИЗ без указания условия связи в секции ГДЕ или использования оператора СОЕДИНЕНИЕ порождает так называемое декартово произведение (Cross Join).
Давайте представим: если в первой таблице ВТ1 содержится 10 000 строк, и во второй таблице ВТ2 также 10 000 строк, то результатом такого «объединения» станет таблица объемом 100 000 000 записей. Каждая строка первой таблицы будет умножена на каждую строку второй. СУБД пытается подготовить этот гигантский объем данных, записывая его во временные файлы, что мгновенно забивает диск С.
Часто программисты замечают, что даже после закрытия сеанса 1С место на диске остается занятым. Разберем, почему это происходит:
tempdb умеет автоматически расширяться, но не умеет автоматически сжиматься. Если запрос «раздул» tempdb до 50 Гб, этот файл останется такого размера до перезагрузки службы SQL или ручного выполнения команды сжатия (Shrink).%TEMP% могут просто не удалиться платформой.МенеджерВременныхТаблиц и он не был явно закрыт, временные таблицы продолжат существовать в базе данных до тех пор, пока объект не будет уничтожен сборщиком мусора.Чтобы избежать подобных проблем, рассмотрим по шагам правильный подход к разработке:
1. Исправление логики объединения. Если ваша задача — просто объединить результаты двух таблиц (добавить строки одной к другой), используйте оператор ОБЪЕДИНИТЬ ВСЕ вместо перечисления таблиц в секции ИЗ. Если же нужно связать данные, всегда указывайте условие связи:
ВЫБРАТЬ
ВТ1.Контрагент,
ВТ2.Сумма
ИЗ
ВТ1 КАК ВТ1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ2 КАК ВТ2
ПО ВТ1.Договор = ВТ2.Договор
2. Явное типизирование колонок ТЗ. Проанализируем важность типов данных. Перед передачей ТаблицыЗначений в запрос, убедитесь, что у каждой колонки жестко задан тип. Если тип колонки не определен или является строкой неограниченной длины, 1С создаст в СУБД максимально «тяжелые» поля (например, nvarchar(max)), что значительно увеличит размер временных таблиц.
3. Использование индексов. Если временная таблица большая и вы планируете соединять её с другими таблицами, обязательно создавайте индекс. Это не уменьшит объем на диске, но колоссально ускорит выполнение запроса и снизит нагрузку на дисковую подсистему.
4. Принудительная очистка. Хорошей практикой считается удаление временных таблиц сразу после того, как они перестали быть нужными. Рассмотрим пример использования команды УНИЧТОЖИТЬ в пакете запросов:
Запрос.Текст =
"ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ;
|/////////////////////////////////////////////////
|ВЫБРАТЬ * ИЗ ВТ_Данные;
|/////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТ_Данные";
Если проблема уже случилась и работа системы парализована, выполним следующие действия:
tempdb с начальным размером. Если перезапуск невозможен, используйте команду DBCC SHRINKFILE в SQL Management Studio.%TEMP%. Нас интересуют файлы и папки, названия которых начинаются на v8_.Соблюдение этих несложных правил позволит вам создавать производительные решения, которые не будут приводить к сбоям в работе инфраструктуры из-за нехватки свободного места.