Использование временных таблиц вместо подзапросов в конструкторе 1С
- Экспоненциальный рост времени выполнения запроса при увеличении объема обрабатываемых документов.
- В плане запроса СУБД появляются операторы
Nested Loopsс миллионами итераций. - Оптимизатор СУБД выбирает ошибочные оценки кардинальности (Cardinality Estimation).
1. Проблема коррелированных подзапросов и условий «В (ВЫБРАТЬ...)»
Использование вложенных подзапросов в условиях соединения или секции ГДЕ Поле В (ВЫБРАТЬ ...) приводит к тому, что СУБД может выполнять подзапрос построчно для каждой строки внешнего источника.
2. Оптимизация: Перенос выборки во временную таблицу
// НЕПРАВИЛЬНО (Подзапрос в условии соединения):
ВЫБРАТЬ
Заказ.Ссылка,
Остатки.КоличествоОстаток
ИЗ Документ.ЗаказКлиента КАК Заказ
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ Номенклатура, СУММА(Количество) КАК КоличествоОстаток
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, )
СГРУППИРОВАТЬ ПО Номенклатура) КАК Остатки
ПО Заказ.Номенклатура = Остатки.Номенклатура;
// ПРАВИЛЬНО (Пакетный запрос с временной таблицей и индексом):
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура,
Остатки.КоличествоОстаток КАК КоличествоОстаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки;
ИНДЕКСИРОВАТЬ ПО
Номенклатура;
;
ВЫБРАТЬ
Заказ.Ссылка,
ВТ_Остатки.КоличествоОстаток
ИЗ Документ.ЗаказКлиента КАК Заказ
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Остатки КАК ВТ_Остатки
ПО Заказ.Номенклатура = ВТ_Остатки.Номенклатура;3. Обязательная индексация полей соединения
Всегда добавляйте инструкцию ИНДЕКСИРОВАТЬ ПО для полей, по которым в последующих запросах пакета происходит ПО (JOIN) или фильтрация ГДЕ.
Частые вопросы (FAQ)
Всегда ли временная таблица быстрее подзапроса?
Для выборок размером более 50-100 строк временная таблица почти всегда быстрее, так как СУБД строит по ней точную статистику и использует быстрые индексные поиски (Index Seek).
Когда подзапрос допустим?
Подзапросы допустимы в простых конструкциях, возвращающих строго одну скалярную величину или выборку до 10-20 записей без соединений.
Где физически создаются временные таблицы 1С?
В СУБД MS SQL Server временные таблицы 1С создаются как реальные таблицы в базе tempdb (#tt*), в PostgreSQL — как локальные временные таблицы сессии pg_temp.
Нужно ли явно уничтожать временные таблицы в конце запроса?
Уничтожать таблицы через 'УНИЧТОЖИТЬ ВТ_Таблица' желательно в длинных пакетных запросах, чтобы освободить оперативную память и пространство tempdb до завершения всего пакета.