При работе с запросами в 1С:Предприятии программисты часто сталкиваются с необходимостью фильтрации данных по полям, имеющим составной тип или Определяемый тип. Особенность таких полей заключается в том, что они могут хранить ссылки на различные объекты метаданных (справочники, документы и т.д.). Неправильный подход к написанию условия в секции ГДЕ может привести не только к ошибкам выполнения запроса, но и к значительным потерям производительности. Разберем подробно, как правильно накладывать условия на такие поля, и проанализируем, почему стандартные конструкции могут давать сбой.
Рассмотрим ситуацию, когда разработчик пытается отфильтровать данные, используя оператор ВЫРАЗИТЬ. Часто это выглядит следующим образом:
ГДЕ
ВЫРАЗИТЬ(ДействияЗадач.ВидПриложения КАК Справочник.ВидыДокументов)
Проанализируем, почему этот код вызывает ошибку. Оператор ВЫРАЗИТЬ предназначен для явного приведения типа значения в выборке. Однако в секции ГДЕ платформа ожидает логическое выражение, результат которого — «Истина» или «Ложь». Само по себе приведение к типу не является логическим условием. Чтобы такая конструкция заработала в фильтре, ее пришлось бы сравнивать с чем-то еще, например:
ГДЕ
ВЫРАЗИТЬ(ДействияЗадач.ВидПриложения КАК Справочник.ВидыДокументов) ЕСТЬ НЕ NULL
Но даже в таком виде это решение далеко от оптимального. Использование ВЫРАЗИТЬ заставляет систему выполнять лишние преобразования типов для каждой строки таблицы. Если типов внутри Определяемого типа много, это создаст избыточную нагрузку на СУБД.
Наиболее правильным и производительным способом проверки типа в запросе 1С является оператор ССЫЛКА. С точки зрения SQL, этот оператор транслируется в максимально простую и быструю проверку идентификатора типа в соответствующей колонке таблицы.
Рассмотрим пример правильного написания условия:
ГДЕ
ДействияЗадач.ВидПриложения ССЫЛКА Справочник.ВидыДокументов
Почему это работает быстрее? Выясним причину, заглянув «под капот» базы данных. Когда вы используете Определяемый тип, СУБД хранит данные в нескольких колонках: одна для идентификатора типа и другие для уникальных идентификаторов (GUID) конкретных объектов. Оператор ССЫЛКА проверяет только колонку идентификатора типа. Это позволяет оптимизатору SQL эффективно отсекать ненужные записи еще до того, как начнется чтение данных самого объекта.
Иногда возникают ситуации, когда конструктор запроса или сама платформа не принимают конструкцию ССЫЛКА. Это часто случается при использовании расширений конфигурации, когда метаданные не успели корректно обновиться в кэше. В этом случае рабочим вариантом будет использование функций ТИПЗНАЧЕНИЯ и ТИП.
Посмотрим на пример кода, который помог автору темы:
ГДЕ
ТИПЗНАЧЕНИЯ(ДействияЗадач.ВидПриложения) = ТИП(Справочник.ВидыДокументов)
Хотя этот вариант функционально идентичен оператору ССЫЛКА, технически он может работать чуть медленнее на огромных массивах данных, так как функция ТИПЗНАЧЕНИЯ вычисляется для каждой строки. Однако на практике разница часто нивелируется оптимизатором запросов 1С.
Важно помнить о специфике работы с расширениями. Если вы добавили новый справочник в расширение и включили его в Определяемый тип также внутри расширения, платформа может «потерять» этот тип при проверке в конструкторе запросов. Проанализируем основные причины возникновения ошибок в таких случаях:
ВидПриложения) написано без ошибок. Даже одна неверная буква приведет к ошибке «Поле не найдено».Определяемого типа в расширении, рекомендуется выполнить полное сохранение конфигурации базы данных и перезагрузить сеанс работы с базой.ССЫЛКА, действительно включен в состав типов этого поля в расширении.Разберем подробнее, как устроены поля с составным типом на уровне СУБД. При создании поля типа Определяемый тип платформа 1С создает в SQL-таблице структуру, зависящую от количества входящих в него типов. Если типов много, таблица «раздувается», так как для каждого типа выделяется место под GUID.
Для оптимизации производительности придерживайтесь следующих правил:
Определяемым типом часто выполняется фильтрация, установите для него свойство Индексировать в метаданных. Без индекса СУБД будет вынуждена выполнять полное сканирование таблицы (Full Table Scan).Определяемый тип лишние объекты «на всякий случай». Чем меньше типов, тем компактнее структура таблицы в SQL.ГДЕ всегда отдавайте приоритет оператору ССЫЛКА, так как он наиболее «родной» для механизмов трансляции запросов 1С.Подводя итог нашему анализу, можно составить пошаговый алгоритм действий при возникновении ошибок фильтрации по составным типам:
ССЫЛКА как наиболее быстрый вариант.ССЫЛКА выдает ошибку в конструкторе (особенно в расширении), использовать связку ТИПЗНАЧЕНИЯ(...) = ТИП(...).ВЫРАЗИТЬ внутри секции ГДЕ для фильтрации типов.Соблюдение этих простых правил позволит вам писать чистый, быстрый и отказоустойчивый код запросов, который будет эффективно работать даже при больших объемах данных и сложной структуре метаданных.