Чёрный пояс 1С. Точка в запросе: сколько неявных соединений вы только что написали | infolimp.ru

Чёрный пояс 1С. Точка в запросе: сколько неявных соединений вы только что написали

12 июня 2026 · infolimp.ru

Запрос на три строки, который читается как проза: Товары.Номенклатура.Производитель.Страна — и отчёт, который шёл две секунды, начинает идти двадцать. В коде при этом не изменилось «ничего»: ни соединений, ни вложенных запросов. Если вы когда-нибудь искали, откуда в плане запроса взялись три JOIN при одном источнике в секции ИЗ, — это тот самый случай.

Вопрос с собеседования

В запросе одна таблица-источник и поле Товары.Номенклатура.Производитель.Страна в выборке. Сколько соединений на самом деле выполнит СУБД? И что изменится, если реквизит окажется составного типа — например, Регистратор.Дата у движений регистра?

Вопрос выглядит школьным, но вторая его половина стабильно разделяет кандидатов на тех, кто читал план запроса, и тех, кто верит тексту на языке 1С буквально.

Что платформа делает за вашей спиной

Каждая точка после ссылочного поля — это обращение к другой таблице. Значение ссылки само по себе не содержит ни наименования, ни производителя — только идентификатор. Чтобы достать «через точку» реквизит, платформа автоматически добавляет в SQL-текст левое соединение с таблицей, на которую ведёт ссылка. Цепочка Номенклатура.Производитель.Страна — это уже три неявных соединения подряд: к номенклатуре, от неё к производителю, от него к стране (при условии, что каждая ссылка простого типа — про составные ниже). В тексте запроса — одна таблица, в плане СУБД — четыре.

Соединение именно левое: если ссылка пустая или битая, строка из результата не пропадает — присоединённые поля просто заполняются NULL. Это удобно и это же коварно: NULL дальше живёт своей жизнью в условиях и агрегатах: сравнение «не равно значению» молча перестаёт ловить такие строки, а фильтр в ГДЕ по полю через точку просто отбросит строку с пустой ссылкой — предикат на NULL не выполнится.

Где цена умножается: составные типы

Теперь главная каверза. Если поле имеет составной тип — классика: Регистратор у движений регистра, куда пишут двадцать видов документов, — платформе некуда сделать одно соединение. Она делает соединение с каждой таблицей, входящей в состав типа. Если в состав типа поля Регистратор у этого регистра входят двадцать видов документов, невинное Регистратор.Дата — это двадцать левых соединений, о которых в тексте запроса нет ни слова; реальное число всегда равно числу типов в составе поля, его видно в конфигураторе. На маленькой базе вы этого не заметите. На большой — заметит СУБД, оптимизатор которой получает план из двух десятков JOIN там, где ожидался один.

Лекарство документированное — оператор ВЫРАЗИТЬ: ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Дата. Явное приведение говорит платформе, какая таблица нужна, и соединение становится одно. Если фактический тип в строке другой — поле вернёт NULL, что честно: вы сами ограничили выборку одним типом.

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

Что с этим делать на проекте

Язык запросов 1С прячет соединения, чтобы код читался, — и читаемость он действительно даёт. Плата за неё видна только в плане СУБД. Старший разработчик отличается не тем, что не пишет точек, а тем, что в каждый момент знает, сколько таблиц они ему стоят.

Профессиональные решения для 1С и marketplace-интеграций — каталог отчётов и инструментов на витрине НОПи.

Перейти в каталог решений →