При написании запросов к регистрам сведений, измерения которых имеют составной тип данных (в частности, ЛюбаяСсылка), разработчики часто сталкиваются с синтаксическими ошибками и критическим падением производительности. Рассмотрим типичную ситуацию: требуется выбрать реквизиты конкретного документа (например, РеализацияТоваровУслуг) из регистра сведений и установить отбор по периоду и типу документа.
Проанализируем исходный вариант запроса, выявим синтаксические и архитектурные ошибки, а затем разберем правильные способы реализации такой выборки.
В исходном запросе условие проверки типа было написано следующим образом:
ГДЕ
ТИПЗНАЧЕНИЯ(Отфактуровка.Документ) = ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг)
Такая запись вызывает синтаксическую ошибку, так как функция ТИПЗНАЧЕНИЯ() возвращает значение с типом Тип, а функция ЗНАЧЕНИЕ() с переданным метаданным именем предназначена для получения предопределенных элементов, значений перечислений или пустых ссылок. Платформа ожидает увидеть конструкцию вроде ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка), но тогда типы выражений слева и справа не совпадут (тип против ссылки).
Для корректного сравнения типов в языке запросов 1С предусмотрены два основных синтаксических механизма:
ТИПЗНАЧЕНИЯ() с литералом типа:
ГДЕ
ТИПЗНАЧЕНИЯ(Отфактуровка.Документ) = ТИП(Документ.РеализацияТоваровУслуг)
ГДЕ
Отфактуровка.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
Синтаксическое исправление условия отбора не решает главной проблемы исходного запроса — неявного разыменования составного ссылочного поля через точку (Отфактуровка.Документ.Номер, Отфактуровка.Документ.Дата и т.д.). Выясним причину, почему такое обращение опасно для информационной базы:
ЛюбаяСсылка включает в себя абсолютно все ссылочные объекты конфигурации: документы, справочники, планы видов характеристик, планы счетов и другие. Когда транслятор 1С встречает конструкцию разыменования поля составного типа через точку, он строит неявные соединения LEFT JOIN со всеми таблицами, входящими в составной тип. Если в метаданных суммарно более 256 таблиц, СУБД Microsoft SQL Server аварийно прервет выполнение запроса из-за превышения жесткого системного лимита на количество соединяемых таблиц в одном выражении.Отфактуровка.Документ.ДоговорКонтрагента.Номер происходит двойное разыменование. Сначала соединяются все возможные таблицы документов, а затем к найденному договору подсоединяется таблица справочника договоров. Это приводит к формированию колоссального плана выполнения в СУБД и многократному росту потребления оперативной памяти сервером.Отфактуровка.Документ.Дата МЕЖДУ ... не позволяет СУБД использовать индекс регистра по измерению Документ. Платформе приходится выполнять полное сканирование таблицы регистра (Table Scan или Index Scan) с параллельным разыменованием всех связанных таблиц.Если требуется оставить регистр сведений в качестве ведущей таблицы, необходимо жестко ограничить составной тип измерения до конкретного документа с помощью функции ВЫРАЗИТЬ() как в секции ВЫБРАТЬ, так и в условиях ГДЕ. Это указывает платформе на необходимость построить соединение только с одной физической таблицей Документ.РеализацияТоваровУслуг:
ВЫБРАТЬ
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).Номер КАК Номер,
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).Дата КАК Дата,
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).ДоговорКонтрагента.Номер КАК ДоговорНомер,
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).ДоговорКонтрагента.Дата КАК ДоговорДата,
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).ЕстьПодписанныйОригинал КАК ЕстьПодписанныйОригинал,
ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).Ответственный КАК Ответственный
ИЗ
РегистрСведений.Отфактуровка КАК Отфактуровка
ГДЕ
Отфактуровка.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
И ВЫРАЗИТЬ(Отфактуровка.Документ КАК Документ.РеализацияТоваровУслуг).Дата МЕЖДУ &НачДата И &КонДата
Рассмотрим более производительный вариант. Так как фильтрация строится по периоду дат документа, эффективнее сделать источником выборки сам документ РеализацияТоваровУслуг, а регистр сведений присоединить через ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Поле Дата у документов входит в состав кластерного индекса, поэтому выборка за период выполнится практически мгновенно:
ВЫБРАТЬ
Реализация.Номер КАК Номер,
Реализация.Дата КАК Дата,
Реализация.ДоговорКонтрагента.Номер КАК ДоговорНомер,
Реализация.ДоговорКонтрагента.Дата КАК ДоговорДата,
Реализация.ЕстьПодписанныйОригинал КАК ЕстьПодписанныйОригинал,
Реализация.Ответственный КАК Ответственный
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Отфактуровка КАК Отфактуровка
ПО Отфактуровка.Документ = Реализация.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &НачДата И &КонДата
Такой подход избавляет запрос от нагромождения конструкций ВЫРАЗИТЬ(), исключает риск лишних соединений и гарантирует корректную работу с индексами базы данных.
Если регистр сведений содержит дополнительные условия отбора (например, по своим специфическим измерениям или ресурсам) и его выборка существенно меньше таблицы документов, разберем пакетное решение:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Отфактуровка.Документ КАК ДокументСсылка
ПОМЕСТИТЬ ВТ_Документы
ИЗ
РегистрСведений.Отфактуровка КАК Отфактуровка
ГДЕ
Отфактуровка.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Реализация.Номер КАК Номер,
Реализация.Дата КАК Дата,
Реализация.ДоговорКонтрагента.Номер КАК ДоговорНомер,
Реализация.ДоговорКонтрагента.Дата КАК ДоговорДата,
Реализация.ЕстьПодписанныйОригинал КАК ЕстьПодписанныйОригинал,
Реализация.Ответственный КАК Ответственный
ИЗ
ВТ_Документы КАК ВТ_Документы
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО ВТ_Документы.ДокументСсылка = Реализация.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &НачДата И &КонДата
Для предотвращения подобных сложностей при проектировании конфигурации следует соблюдать стандарты разработки 1С:
ЛюбаяСсылка для реквизитов и измерений. Указывайте только те конкретные типы документов, которые действительно могут быть записаны в данный регистр.