В процессе разработки сложных запросов в системе 1С:Предприятие программисты часто сталкиваются с необходимостью соединения двух таблиц по внушительному списку полей. Типичный пример — соединение по измерениям регистра накопления, количество которых может достигать 5, 9 и более. Возникает закономерный вопрос: как прописать условие связи в секции ПО, чтобы запрос работал максимально быстро и эффективно использовал индексы СУБД? Рассмотрим основные подходы, их преимущества и скрытые угрозы.
Это наиболее распространенный и «родной» для СУБД способ. Мы перечисляем все пары полей через логическое «И».
ИЗ
Таблица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. Это позволяет не сканировать всю таблицу целиком, а быстро находить нужные записи.
Иногда разработчики пытаются сократить код, используя сравнение кортежей (списков полей):
ИЗ
Таблица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), что на больших объемах данных приведет к катастрофическому падению производительности.
Выясним причину, по которой эти два варианта могут выдавать разные результаты. В языке SQL значение NULL коварно: выражение NULL = NULL возвращает Unknown (ложь для фильтра), а не True.
Если в ваших измерениях могут встречаться пустые значения (NULL), то:
= строки с NULL просто не соединятся.В логика может измениться в зависимости от того, как 1С преобразует запрос для конкретной СУБД.Поэтому, если ваши поля допускают NULL, правильно будет использовать функцию ЕСТЬNULL или явно проверять значения, хотя для соединений по измерениям регистров 1С это обычно не требуется (так как измерения в регистрах чаще всего имеют значения по умолчанию, а не физический NULL).
Рассмотрим подробнее, как количество условий влияет на выбор алгоритма соединения:
= и наличии индекса СУБД выберет именно его.В), СУБД может построить хеш-таблицу в памяти. Если памяти не хватит, данные полетят в tempdb на диск, и запрос «умрет».В, может заставить СУБД выбрать этот метод там, где он не применим.Если вы проектируете собственную систему или расширение, и вам постоянно нужно соединять таблицы по 9-10 полям, стоит посмотреть на архитектуру типовых конфигураций (например, УТ 11 или ERP 2). Там используется механизм Ключей аналитики.
Суть метода: 1. Создается отдельный справочник (или таблица), где хранится уникальная комбинация всех ваших 9 измерений. 2. Этой комбинации присваивается один короткий идентификатор (ссылка или число). 3. В регистрах вместо 9 полей хранится только один этот идентификатор. 4. Соединение происходит по одному полю, что работает молниеносно.
Если же вы работаете с типовым регистром, где 9 измерений уже есть, и классическое соединение через = тормозит, воспользуемся проверенным алгоритмом оптимизации через временные таблицы:
ВТ_Данные1.ВТ_Данные2.=.Это гарантирует, что СУБД получит актуальную статистику по временным таблицам и построит максимально эффективный план запроса.
Проанализировав все варианты, можно сделать однозначный вывод: оператор "=" является безусловным фаворитом. Вариант с использованием В для кортежей полей — это «синтаксический сахар», который в большинстве случаев вредит производительности. Если условий связи слишком много, и запрос работает медленно, проблему нужно решать не сменой оператора, а использованием временных таблиц с индексами или внедрением ключей аналитики.