Что лучше использовать в запросе 1С для соединения таблиц по нескольким полям: оператор "=" или "В"?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки сложных запросов в системе 1С:Предприятие программисты часто сталкиваются с необходимостью соединения двух таблиц по внушительному списку полей. Типичный пример — соединение по измерениям регистра накопления, количество которых может достигать 5, 9 и более. Возникает закономерный вопрос: как прописать условие связи в секции ПО, чтобы запрос работал максимально быстро и эффективно использовал индексы СУБД? Рассмотрим основные подходы, их преимущества и скрытые угрозы.

Вариант 1: Классическое соединение через оператор "="

Это наиболее распространенный и «родной» для СУБД способ. Мы перечисляем все пары полей через логическое «И».


ИЗ
    Таблица1 КАК Т1
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица2 КАК Т2
    ПО Т1.Измерение1 = Т2.Измерение1
    И Т1.Измерение2 = Т2.Измерение2
    И Т1.Измерение3 = Т2.Измерение3
    ...
    И Т1.Измерение9 = Т2.Измерение9

Почему это хорошо: Платформа 1С транслирует такую конструкцию в классический JOIN с условиями в секции ON. Оптимизаторы современных СУБД (MS SQL Server, PostgreSQL) идеально «понимают» этот синтаксис. Они могут легко оценить селективность каждого поля, использовать статистику и построить оптимальный план выполнения.

Разберем подробнее работу с индексами. Если для таблиц существуют подходящие составные индексы, включающие эти измерения, СУБД с высокой вероятностью выполнит операцию Index Seek или Merge Join. Это позволяет не сканировать всю таблицу целиком, а быстро находить нужные записи.

Вариант 2: Использование кортежей и оператора "В"

Иногда разработчики пытаются сократить код, используя сравнение кортежей (списков полей):


ИЗ
    Таблица1 КАК Т1
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица2 КАК Т2
    ПО (Т1.Измерение1, Т1.Измерение2) В (Т2.Измерение1, Т2.Измерение2)

Проанализируем ситуацию: этот вариант считается крайне неудачным для задач соединения. Во-первых, MS SQL Server не поддерживает синтаксис сравнения кортежей напрямую в секции JOIN. Платформе 1С приходится выполнять сложную трансляцию этого выражения, что часто превращает его в набор тяжелых условий EXISTS или громоздких логических конструкций. Это «запутывает» оптимизатор СУБД.

Во-вторых, использование оператора В часто делает предикаты не-SARGable (Searchable Arguments). Это означает, что СУБД не сможет использовать быстрый поиск по индексу (Index Seek) и будет вынуждена прибегнуть к полному сканированию индекса (Index Scan), что на больших объемах данных приведет к катастрофическому падению производительности.

Проблема обработки значений NULL

Выясним причину, по которой эти два варианта могут выдавать разные результаты. В языке SQL значение NULL коварно: выражение NULL = NULL возвращает Unknown (ложь для фильтра), а не True.

Если в ваших измерениях могут встречаться пустые значения (NULL), то:

  1. При использовании = строки с NULL просто не соединятся.
  2. При использовании В логика может измениться в зависимости от того, как 1С преобразует запрос для конкретной СУБД.

Поэтому, если ваши поля допускают NULL, правильно будет использовать функцию ЕСТЬNULL или явно проверять значения, хотя для соединений по измерениям регистров 1С это обычно не требуется (так как измерения в регистрах чаще всего имеют значения по умолчанию, а не физический NULL).

Стратегии оптимизации СУБД: Merge Join vs Hash Join

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

Продвинутое решение: Использование Ключей Аналитики

Если вы проектируете собственную систему или расширение, и вам постоянно нужно соединять таблицы по 9-10 полям, стоит посмотреть на архитектуру типовых конфигураций (например, УТ 11 или ERP 2). Там используется механизм Ключей аналитики.

Суть метода: 1. Создается отдельный справочник (или таблица), где хранится уникальная комбинация всех ваших 9 измерений. 2. Этой комбинации присваивается один короткий идентификатор (ссылка или число). 3. В регистрах вместо 9 полей хранится только один этот идентификатор. 4. Соединение происходит по одному полю, что работает молниеносно.

Золотой стандарт 1С: Временные таблицы

Если же вы работаете с типовым регистром, где 9 измерений уже есть, и классическое соединение через = тормозит, воспользуемся проверенным алгоритмом оптимизации через временные таблицы:

  1. Выберем необходимые данные из первой таблицы во временную таблицу ВТ_Данные1.
  2. Выберем данные из второй таблицы во временную таблицу ВТ_Данные2.
  3. Обязательно проиндексируем обе временные таблицы по тем полям, по которым будет идти связь (хотя бы по 3-4 самым уникальным).
  4. Выполним финальное соединение этих временных таблиц через оператор =.

Это гарантирует, что СУБД получит актуальную статистику по временным таблицам и построит максимально эффективный план запроса.

Резюме

Проанализировав все варианты, можно сделать однозначный вывод: оператор "=" является безусловным фаворитом. Вариант с использованием В для кортежей полей — это «синтаксический сахар», который в большинстве случаев вредит производительности. Если условий связи слишком много, и запрос работает медленно, проблему нужно решать не сменой оператора, а использованием временных таблиц с индексами или внедрением ключей аналитики.

← На главную