Корректно ли соединять физические таблицы напрямую в запросах 1С или использовать временные таблицы

Программист IT и автоматизация бизнеса
← На главную

При разработке запросов в платформе 1С:Предприятие часто возникает вопрос: допустимо ли соединять физические таблицы информационной базы (например, справочники или документы) напрямую через конструкцию ЛЕВОЕ СОЕДИНЕНИЕ / ВНУТРЕННЕЕ СОЕДИНЕНИЕ, или же правильнее сначала поместить данные одной из таблиц во временную таблицу?

Разберем логику работы СУБД, оценим производительность каждого подхода и выясним, в каких ситуациях прямое соединение является оптимальным, а когда без временных таблиц не обойтись.

Прямое соединение физических таблиц: базовый подход

Прямое соединение двух и более физических таблиц — это абсолютно корректная и стандартная практика в языке запросов 1С. В подавляющем большинстве случаев (около 95–98%) именно такое написание запроса дает лучшую производительность, так как оптимизатор СУБД (MS SQL Server, PostgreSQL) самостоятельно строит наиболее эффективный план выполнения.

Рассмотрим пример стандартного прямого соединения справочника номенклатуры и документа:


ВЫБРАТЬ
	РеализацияТоваров.Ссылка КАК Документ,
	РеализацияТоваров.Контрагент КАК Контрагент,
	Номенклатура.Наименование КАК Номенклатура
ИЗ
	Документ.РеализацияТоваровУслуг КАК РеализацияТоваров
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		ПО РеализацияТоваров.Товары.Номенклатура = Номенклатура.Ссылка

В данном случае оптимизатор СУБД использует существующие первичные индексы таблиц и выбирает наилучший алгоритм соединения (например, Nested Loops или Hash Join). Создание временной таблицы для такой операции было бы избыточным и привело бы к лишним накладным расходам.

Когда прямое соединение работает неоптимально

Проблемы с производительностью при прямом соединении возникают в следующих ситуациях:

  1. Соединение по неиндексированным полям: Если выборка соединяется по реквизиту, для которого не включено свойство «Индексировать» в метаданных, СУБД вынуждена сканировать всю таблицу целиком (осуществлять Table Scan или Index Scan).
  2. Использование неявных соединений (разыменование через точку): При обращении к реквизитам через ссылку в блоке ПО или ГДЕ (например, Документ.Контрагент.ОсновнойДоговор) платформа автоматически создает дополнительные внешние соединения, усложняя план запроса.
  3. Соединение с вложенными подзапросами: Если физическая таблица соединяется с конструкцией вида ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ...), оптимизатор СУБД часто не может корректно оценить количество строк (cardinality), что ведет к выбору медленного алгоритма выполнения.

В каких случаях необходимы временные таблицы

Помещение данных из физической таблицы во временную перед основным соединением оправдано в следующих сценариях:

1. Повторное использование данных в пакетном запросе. Если данные из физической таблицы требуются в нескольких запросах одного пакета, предварительная выборка во временную таблицу сокращает количество обращений к дисковой подсистеме СУБД.

2. Соединение по неиндексированным реквизитам. При помещении данных во временную таблицу можно явно создать индекс по полям связи с помощью инструкции ИНДЕКСИРОВАТЬ ПО:


ВЫБРАТЬ
	Контрагенты.Ссылка КАК Контрагент,
	Контрагенты.КодПоОКПО КАК ОКПО
ПОМЕСТИТЬ ВТ_Контрагенты
ИЗ
	Справочник.Контрагенты КАК Контрагенты
ГДЕ
	НЕ Контрагенты.ЭтоГруппа

ИНДЕКСИРОВАТЬ ПО
	ОКПО
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ_Контрагенты.Контрагент КАК Контрагент,
	ДругаяТаблица.Данные КАК Данные
ИЗ
	ВТ_Контрагенты КАК ВТ_Контрагенты
	ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВнешниеДанные КАК ДругаяТаблица
		ПО ВТ_Контрагенты.ОКПО = ДругаяТаблица.ОКПО

3. Разделение сложных группировок и фильтрации. Если перед соединением данные необходимо предварительно сгруппировать, отфильтровать или агрегировать, рекомендуется вынести эти операции во временную таблицу, чтобы упростить итоговый запрос для оптимизатора СУБД.

Накладные расходы при работе с временными таблицами

Необходимо помнить, что временные таблицы создаются во временной служебной базе СУБД (TempDB в MS SQL Server или tempdb в PostgreSQL). Это связано с накладными расходами:

  1. Затраты на ввод-вывод (I/O): Операции создания, записи и удаления временных таблиц требуют ресурсов диска и процессора. Для небольших наборов данных (десятки или сотни строк) эти затраты превышают возможную выгоду.
  2. Объем данных: Помещать во временные таблицы сотни тысяч или миллионы записей не рекомендуется, так как это вызывает переполнение служебной базы данных и нагрузки на журнал транзакций.

Итоговые рекомендации

Проанализировав оба подхода, сформулируем практические правила:

  1. Соединяйте физические таблицы напрямую, если условия связи идут по индексированным полям (Ссылка, первичные ключи) и выборка не требует сложной предварительной агрегации.
  2. Используйте временные таблицы с секцией ИНДЕКСИРОВАТЬ ПО, если связь выполняется по неиндексированным полям или исходные данные участвуют в нескольких запросах пакета.
  3. Всегда ограничивайте состав полей во временных таблицах — выбирайте только ключи связи и минимально необходимые значения.
← На главную