Стандарт 657: Параметры виртуальной таблицы не должны содержать подзапросы
Название проверки
Напишите краткое название проверки
Английское название проверки
Напишите английское название проверки
Правило анализа кода/метаданных
При обращении к виртуальной таблице следует передавать в условия наиболее простые конструкции, например, "Измерение = Значение". Не рекомендуется использовать подзапросы и соединения(*) в параметрах виртуальной таблицы, так как это приводит к медленной работе запроса.
- Примечание: как явные соединения в подзапросах, так и неявные – при обращении к полям «через точку» от ссылки и соединения, добавляемые из ограничений доступа к данным (RLS), предусмотренных в ролях конфигурации.
Мета-информация (пожалуйста, заполните если знаете):
- Номер стандарта:
657 - Код проверки:
ql-virtual-table-parameter-subquery - Тип ошибки:
PERFORMANCE - Критичность:
MAJOR - Код ошибки АПК:
нет
Параметры проверки
Текст ошибки
Пример некорректного решения
... ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(
&ДатаОтгрузки,
&ОтображениеРаспоряжений
И ДокументОтгрузки.Склад = &Склад -- неявное соединение «через точку»
ИЛИ ДокументОтгрузки В
(ВЫБРАТЬ -- подзапрос с соединением
Распоряжения.Распоряжение КАК ДокументОтгрузки
ИЗ
Документ.ЗаданиеНаПеревозку.Распоряжения КАК Распоряжения –- доступ к этому документу ограничен по сложному RLS, который неявно добавляет еще пару соединений
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаданиеНаПеревозку.СкладыПогрузки КАК СкладыПогрузки
ПО
Распоряжения.Ссылка = СкладыПогрузки.Ссылка
И СкладыПогрузки.Склад = &Склад
И Распоряжения.Ссылка.Проведен –- здесь и ниже обращения к реквизитам шапки
И Распоряжения.Ссылка.Статус В (...)))
Описание, почему так делать нельзя
При необходимости использовать подзапросы рекомендуется соблюдать следующие условия:
- в подзапросе только одна таблица, нет соединений с другими таблицами;
- если в подзапросе таблица табличной части (например, Документ.Накладная.СписокТоваров), то не должно быть обращения к реквизитам таблицы-шапки (Накладная.Проведен);
- если в подзапросе таблица, у которой могут быть табличные части (например, Документ.Накладная), то не должно быть обращений к табличным частям (например, ГДЕ Документ.Накладная.СписокТоваров.Номенклатура = "1");
- если в подзапросе временная таблица, то не должно быть условий (раздела ГДЕ);
- если в подзапросе постоянная таблица, то условие (раздел ГДЕ) допустимо, только если условие выполняется для 80% (или более) случаев; отсутствие условия означает выполнение для 100% случаев.
- если в подзапросе постоянная таблица, то в ограничениях доступа к данным (RLS) не должно содержатся подзапросов и соединений (допускаются только простые условия вида ГДЕ Реквизит = Значение, "ГДЕ Истина"). Например, при использовании стандартных шаблонов RLS, входящих в состав подсистемы «Управление доступом» Библиотеки стандартных подсистем к запросу неявно добавляется конструкция Exists с несколькими подзапросами и соединениями. В таких случаях следует переписать исходный запрос с использованием временной таблицы или привилегированного режима.
Пример корректного решения
... ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(
&ДатаОтгрузки,
Склад = &Склад -- теперь это реквизит регистра
ИЛИ ДокументОтгрузки В
(ВЫБРАТЬ
ЗаданияНаПеревозку.Распоряжение
ИЗ
ВременнаяТаблицаЗаданийНаПеревозку КАК ЗаданияНаПеревозку)) -- выборка из временной таблицы без условий
Пример некорректного решения
Номенклатура В (...) И Характеристика В (...) И Серия В(...)
Описание, почему так делать нельзя
В случае, если нужно использовать несколько условий с подзапросами, следует выбрать одно, удовлетворяющее условиям выше и отфильтровывающее максимальное количество записей. Остальные условия следует накладывать на внешний запрос.
Кроме того, в ряде случаев можно обойтись и без перемещения условий на внешний запрос, если применять временные таблицы.
Пример корректного решения
(Номенклатура, Характеристика, Серия) В (ВЫБРАТЬ Номенклатура, Характеристика, Серия ИЗ ВременнаяТаблицаТоваров)
Дополнительные материалы
взял в работу