В среде разработчиков 1С часто можно услышать о «смертном грехе» — обращении к реквизитам через точку в текстах запросов. Существует мнение, что это всегда ведет к деградации производительности и созданию неоптимальных планов запросов на стороне SQL-сервера. В данной статье мы подробно разберем, так ли это на самом деле, проанализируем внутренние механизмы платформы и выясним, в каких ситуациях использование «точек» допустимо, а в каких — категорически запрещено.
Когда мы пишем в запросе конструкцию вида ФактическоеРабочееВремяСотрудников.Сотрудник.Магазин, платформа 1С:Предприятие не передает этот текст в СУБД в исходном виде. Вместо этого она выполняет трансформацию запроса, заменяя обращение через точку на неявное левое соединение (LEFT OUTER JOIN). Рассмотрим это на примере из обсуждения:
ВЫБРАТЬ
ФактическоеРабочееВремяСотрудников.Сотрудник КАК Сотрудник
ИЗ
РегистрНакопления.ФактическоеРабочееВремяСотрудников КАК ФактическоеРабочееВремяСотрудников
ГДЕ
ФактическоеРабочееВремяСотрудников.Сотрудник.Магазин = &Магазин
В данном случае, если поле Сотрудник имеет простой ссылочный тип (например, СправочникСсылка.ФизическиеЛица), платформа сформирует SQL-запрос, в котором таблица регистра будет соединена с таблицей справочника физических лиц по полю Ссылка. Проанализируем ситуацию: если тип поля одиночный (не составной), то такое обращение практически идентично явному левому соединению, написанному вручную. СУБД (например, MS SQL Server) в большинстве случаев построит один и тот же план выполнения для обоих вариантов.
Ситуация кардинально меняется, когда мы обращаемся через точку к полю составного типа. Классический пример — поле Регистратор в регистрах накопления или бухгалтерии. Если в качестве регистраторов указано, скажем, 20 различных видов документов, то при написании Регистратор.Номер платформа будет вынуждена выполнить соединение со всеми 20 таблицами этих документов.
Рассмотрим, почему это критично:
Как отмечалось в обсуждении, обращение регОбороты.Регистратор.Комментарий — это прямой путь к серьезным проблемам с производительностью, если список регистраторов велик.
Если нам все же необходимо получить данные из составного поля, мы должны помочь платформе и СУБД, ограничив выборку конкретным типом. Для этого используем оператор ВЫРАЗИТЬ. Проанализируем пример:
ВЫБРАТЬ
ВЫРАЗИТЬ(Обороты.Регистратор КАК Документ.РеализацияТоваровУслуг).Склад КАК Склад
ИЗ
РегистрНакопления.Продажи.Обороты КАК Обороты
В этом случае платформа создаст LEFT JOIN только с одной таблицей — документом «Реализация товаров и услуг». Все остальные типы документов будут проигнорированы, что значительно ускорит выполнение запроса.
Выясним, когда стоит отказаться от точек в пользу явного СОЕДИНЕНИЯ в секции ИЗ. Рассмотрим запрос, предложенный в теме для сравнения:
ВЫБРАТЬ
ФактическоеРабочееВремяСотрудников.Сотрудник КАК Сотрудник
ИЗ
РегистрНакопления.ФактическоеРабочееВремяСотрудников КАК ФактическоеРабочееВремяСотрудников
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК спрСотрудники
ПО ФактическоеРабочееВремяСотрудников.Сотрудник = спрСотрудники.Ссылка
ГДЕ
спрСотрудники.Магазин = &Магазин
Преимущества явного соединения:
ЛЕВОЕ СОЕДИНЕНИЕ. Если вам нужно отсечь пустые значения или записи, для которых нет соответствия в справочнике, ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN) будет работать эффективнее и корректнее.Особое внимание следует уделить условиям в параметрах виртуальных таблиц (например, СрезПоследних или Обороты). Написание условия типа Сотрудник.Магазин = &Магазин внутри параметров виртуальной таблицы — это грубая ошибка. Платформа сначала выберет данные из регистра, а уже потом будет накладывать фильтр по магазину через соединение. Правильнее сначала получить список ссылок сотрудников нужного магазина во временную таблицу, а затем передать её в параметры виртуальной таблицы через условие Сотрудник В (ВЫБРАТЬ Ссылка ИЗ ВТ_СотрудникиМагазина).
Подведем итог и сформулируем правила «хорошего тона» при написании запросов:
ВЫРАЗИТЬ запрещено. Всегда ограничивайте тип данных.ВНУТРЕННЕЕ СОЕДИНЕНИЕ или использование временных таблиц.Соблюдение этих правил позволит вам писать не только работающий, но и быстрый код, который не вызовет проблем при масштабировании информационной системы.