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