Как ускорить и оптимизировать запрос к регистру сведений «ЗначенияСвойствОбъектов» в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Проанализируем исходный проблемный запрос:


ВЫБРАТЬ
    ЗначенияСвойствОбъектов.Объект,
    ЗначенияСвойствОбъектов.Свойство,
    ЗначенияСвойствОбъектов.Значение
ИЗ
    РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
ГДЕ
    ЗначенияСвойствОбъектов.Объект.Ссылка = &Ссылка
    И ЗначенияСвойствОбъектов.Свойство.НазначениеСвойства = ЗНАЧЕНИЕ(ПланВидовХарактеристик.НазначенияСвойствКатегорийОбъектов.Справочник_ХарактеристикиНоменклатуры)
    И (ЗначенияСвойствОбъектов.Свойство = &ДатаН
            ИЛИ ЗначенияСвойствОбъектов.Свойство = &ДатаК)

Причина 1. Разыменование ссылки через точку (Объект.Ссылка)

Выясним причину первой ошибки: конструкция ЗначенияСвойствОбъектов.Объект.Ссылка = &Ссылка заставляет платформу выполнять неявное левое соединение (LEFT JOIN) с таблицей объекта. Поскольку измерение Объект имеет составной тип данных, СУБД генерирует соединения сразу со всеми возможными таблицами типов, входящими в составной тип. Это приводит к значительному усложнению плана выполнения и полной потере эффективности использования индексов.

Посмотрим на исправление: так как в измерении Объект уже хранится ссылка на элемент, обращение через точку не требуется. Сравниваем поле напрямую с параметром:


ГДЕ
    ЗначенияСвойствОбъектов.Объект = &Ссылка

Причина 2. Неявное соединение при фильтрации по реквизиту свойства

В исходном запросе используется фильтрация ЗначенияСвойствОбъектов.Свойство.НазначениеСвойства = .... Это очередное обращение через точку в секции ГДЕ, которое строит соединение с таблицей плана видов характеристик для каждой записи регистра, прошедшей первичный отбор.

Разберем способы устранения этой проблемы:

  1. Передача готового массива свойств в параметр: Если список нужных свойств известен заранее или его можно получить предварительно в коде, мы отбираем свойства до выполнения основного запроса и передаем их готовым списком.
  2. Использование временных таблиц: Если список свойств необходимо определять динамически, отбираем нужные свойства отдельным запросом в пакетном режиме, помещаем их во временную таблицу и связываем с регистром через ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Причина 3. Использование условия ИЛИ

Конструкция (Свойство = &ДатаН ИЛИ Свойство = &ДатаК) в блоке ГДЕ часто мешает оптимизатору СУБД использовать индекс по измерению Свойство, приводя к сканированию диапазона или всей таблицы. Разберем, как это переписать:

  1. Использование оператора В с массивом параметров: Передаем список параметров через массив Свойство В (&МассивСвойств).
  2. Использование ОБЪЕДИНИТЬ ВСЕ: Если требуется выбрать два конкретных свойства, надежным решением на уровне СУБД является объединение двух простых точечных запросов.

Итоговый оптимизированный вариант запроса

Объединим все рекомендации и посмотрим на оптимальный текст запроса с предварительным отбором свойств через временную таблицу:


ВЫБРАТЬ
    Свойства.Ссылка КАК Свойство
ПОМЕСТИТЬ ВТ_НужныеСвойства
ИЗ
    ПланВидовХарактеристик.СвойстваОбъектов КАК Свойства
ГДЕ
    Свойства.Ссылка В (&МассивСвойств)
    И Свойства.НазначениеСвойства = ЗНАЧЕНИЕ(ПланВидовХарактеристик.НазначенияСвойствКатегорийОбъектов.Справочник_ХарактеристикиНоменклатуры)
ИНДЕКСИРОВАТЬ ПО
    Свойство
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗначенияСвойств.Объект КАК Объект,
    ЗначенияСвойств.Свойство КАК Свойство,
    ЗначенияСвойств.Значение КАК Значение
ИЗ
    ВТ_НужныеСвойства КАК ВТ_НужныеСвойства
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
        ПО ВТ_НужныеСвойства.Свойство = ЗначенияСвойств.Свойство
ГДЕ
    ЗначенияСвойств.Объект = &Ссылка

Альтернативное решение: чтение через объектную модель НаборЗаписей

Если в коде требуется точечно получить значения свойств для одного конкретного объекта, часто быстрее и эффективнее отказаться от выполнения произвольного текста запроса и использовать объект РегистрСведенийНаборЗаписей. Платформа 1С транслирует чтение набора записей в максимально простой SQL-запрос с прямым попаданием в кластерный индекс регистра.

Рассмотрим пример на встроенном языке:


Набор = РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьНаборЗаписей();
Набор.Отбор.Объект.Установить(СсылкаНаОбъект);
Набор.Прочитать();

Для Каждого Запись Из Набор Цикл
    Если Запись.Свойство = СвойствоДатаН Или Запись.Свойство = СвойствоДатаК Тогда
        // Обработка полученных значений
        Значение = Запись.Значение;
    КонецЕсли;
КонецЦикла;

Дополнительные факторы производительности

При оптимизации работы с дополнительными реквизитами обратим внимание на следующие архитектурные моменты:

  1. Влияние RLS (ограничение прав на уровне записей): Если запрос выполняется в контексте пользователя с ограниченными правами, платформа добавляет дополнительные подзапросы для проверки прав. Для служебных алгоритмов выполняем операцию в привилегированном режиме с помощью метода УстановитьПривилегированныйРежим(Истина).
  2. Функции БСП: Если в конфигурации используется Библиотека стандартных подсистем, рекомендуется применять функции общего модуля УправлениеСвойствами. В них уже реализовано внутреннее кеширование структуры свойств и оптимизированная выборка.
  3. Актуальность статистики СУБД: Поскольку регистры сведений быстро растут, устаревшая статистика индексов заставляет оптимизатор базы данных выбирать неоптимальный план (Index Scan вместо Index Seek). Регулярно проводим регламентные процедуры обновления статистики и дефрагментации индексов на сервере СУБД.
← На главную