Платформа 1С:Предприятие 8
09.12.2013

Использование параметра Условие при обращении к виртуальной таблице

Проблема

Использование сложных конструкций в параметре Условие при обращении к виртуальной таблице приводит к медленной работе запроса.

Пояснение

Виртуальная таблица - это удобная вещь для обращения к данным регистра. Виртуальная таблица скрывает подробности своей работы, предоставляя понятный способ обращения к данным. В частности, виртуальная таблица по-разному формирует запросы к базе данных в зависимости от того, какой режим работы у регистра (включено ли хранение актуальных итогов, рассчитаны ли итоги и на какой последний период). Она может как использовать временные таблицы базы данных, так и сформировать подзапрос.

Параметр Условие предназначен для того, чтобы сократить объем данных, обрабатываемый при работе виртуальной таблицы. Важно понимать, что при использовании временной таблицы никакой оптимизатор СУБД не сможет распознать, что из временной таблицы в последствии будет использована лишь часть данных, а следовательно без правильного указания параметра Условие заполнение временной таблицы ненужными данными часто может быть причиной проблем с производительностью.

С другой стороны, если в параметр Условие заложить слишком много, то такой подход также может принести больше проблем, нежели пользы.

В процессе разбора одной из проблем производительности в конфигурации был обнаружен запрос к виртуальной таблице регистра, при этом в параметре Условие было указано выражение с подзапросом и соединениями двух табличных частей. Более того, из-за использования неявных соединений (использования выражения через точку в выражении языка запросов) количество таблиц в этом выражении выросло еще больше. Это привело к отрицательному результату - вместо увеличения производительности получилось уменьшение скорости работы.

Рекомендация

При обращении к виртуальной таблице следует передавать в условия наиболее простые конструкции, например, "Измерение = Значение". Не рекомендуется использовать подзапросы и соединения(*) в параметрах виртуальной таблицы, так как это приводит к медленной работе запроса.

(*) Примечание. Как явные соединения в подзапросах, так и неявные – при обращении к полям "через точку" от ссылки и соединения, добавляемые из ограничений доступа к данным (RLS), предусмотренных в ролях конфигурации.

Если все же без подзапросов не обойтись, то рекомендуется соблюдать следующие условия:

Например, неправильно:

Копировать в буфер обмена
... ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(
&ДатаОтгрузки,
&ОтображениеРаспоряжений
 И ДокументОтгрузки.Склад = &Склад      // неявное соединение «через точку»
 ИЛИ ДокументОтгрузки В
  (ВЫБРАТЬ                          // подзапрос с соединением
   Распоряжения.Распоряжение КАК ДокументОтгрузки
  ИЗ
  Документ.ЗаданиеНаПеревозку.Распоряжения КАК Распоряжения // доступ к этому документу ограничен по сложному RLS, который неявно добавляет еще пару соединений
  ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаданиеНаПеревозку.СкладыПогрузки КАК  СкладыПогрузки 
  ПО
  Распоряжения.Ссылка = СкладыПогрузки.Ссылка
  И СкладыПогрузки.Склад = &Склад
  И Распоряжения.Ссылка.Проведен     // здесь и ниже обращения к реквизитам шапки
  И Распоряжения.Ссылка.Статус В (...)))

Правильно:

Копировать в буфер обмена

... ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(
&ДатаОтгрузки,
Склад = &Склад                  // теперь это измерение регистра
ИЛИ ДокументОтгрузки В
(ВЫБРАТЬ
  ЗаданияНаПеревозку.Распоряжение
  ИЗ
  ВТЗаданияНаПеревозку КАК ЗаданияНаПеревозку))  // выборка из временной таблицы без условий

В случае, если нужно использовать несколько условий с подзапросами следует выбрать одно, удовлетворяющее условиям выше и отфильтровывающее максимальное количество записей. Остальные условия следует накладывать на внешний запрос.