Как оптимизировать работу ОбработкаПолученияПредставления и почему замер производительности показывает замедление

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

При разработке конфигураций на платформе 1С:Предприятие 8.3 одной из часто используемых возможностей является переопределение стандартного представления объектов. Это позволяет выводить в списках, полях ввода и сообщениях не просто Наименование или Код, а сложную строку, составленную из нескольких реквизитов. Однако именно здесь программисты часто сталкиваются с серьезными проблемами производительности. В этой статье мы разберем, почему стандартные методы получения данных могут «тормозить» систему и как сделать формирование представления максимально быстрым.

Анализ проблемы: почему стандартный запрос к базе данных — это плохо

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


Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // Вариант 1: Использование стандартного приведения к строке
    Представление = Данные.Наименование + "(" + Строка(Данные.SpaceTypesMain) + ")";
    
    // Вариант 2: Использование функции общего назначения
    Представление = Данные.Наименование + "(" + ОбщегоНазначения.ПолучитьЗначениеРеквизита(Данные.SpaceTypesMain, "Наименование") + ")";
КонецПроцедуры

Замер производительности показывает, что Вариант 2 работает значительно медленнее. Выясним причину. Функция ОбщегоНазначения.ПолучитьЗначениеРеквизита внутри себя выполняет полноценный запрос ВЫБРАТЬ... ИЗ к базе данных. Если пользователь открывает список, в котором отображается 50 строк, платформа вызовет этот обработчик 50 раз. Это классическая проблема «N+1 запросов», когда вместо одного запроса к базе данных для получения списка мы получаем один основной и 50 дополнительных для каждой строки. Каждый такой запрос — это сетевой пакет, время на установку соединения, парсинг запроса СУБД и получение результата.

Магия кэширования платформы: почему Строка() работает быстрее

Теперь разберем, почему Вариант 1 оказывается эффективнее. Когда мы вызываем функцию Строка() от ссылочного типа, платформа 1С задействует механизмы внутреннего кэширования:

  1. Кэш представлений: Платформа хранит представления ссылок в памяти сеанса. Если представление для конкретной ссылки уже вычислялось ранее, 1С возьмет его из памяти, не обращаясь к базе данных.
  2. Оптимизированное чтение: Даже если данных в кэше нет, механизм Строка(Ссылка) работает быстрее, чем произвольный запрос через точку, так как он запрашивает только те поля, которые участвуют в стандартном представлении (обычно это Наименование или Код), а не весь объект целиком.
  3. Жизненный цикл кэша: Кэш представлений инвалидируется (сбрасывается) при изменении объекта, что гарантирует актуальность данных при минимальных затратах ресурсов.

Важно понимать, что «разыменование» ссылок через точку (например, Данные.Ссылка.Реквизит) внутри этого обработчика — это худшее, что можно сделать. В этом случае платформа может прочитать весь объект из базы данных, что при работе с тяжелыми справочниками приведет к катастрофическому падению производительности.

Правильное решение через ОбработкаПолученияПолейПредставления

Для того чтобы данные для представления подтягивались максимально эффективно, в платформе предусмотрено парное событие — ОбработкаПолученияПолейПредставления. Давайте разберем, как его использовать, чтобы избежать лишних запросов.

Этот обработчик позволяет указать платформе, какие именно поля самого объекта ей нужно прочитать из базы заранее, чтобы они попали в структуру Данные первого обработчика. Проанализируем алгоритм реализации:


Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Поля.Добавить("Наименование");
    Поля.Добавить("SpaceTypesMain"); // Добавляем ссылку на вложенный справочник
КонецПроцедуры

После того как мы добавили поля в этом обработчике, платформа автоматически включит их в основной запрос, который формирует динамический список или выбирает данные для формы. Таким образом, в ОбработкаПолученияПредставления параметр Данные уже будет содержать готовые значения, и нам не придется обращаться к серверу БД повторно.

Важное ограничение: К сожалению, платформа не позволяет добавлять поля через точку от ссылочных реквизитов в этом обработчике (например, нельзя написать Поля.Добавить("SpaceTypesMain.Наименование")). Платформа работает только с плоскими реквизитами текущего объекта.

Экстремальная оптимизация: денормализация данных

Если ваша система высоконагруженная и списки открываются сотнями пользователей одновременно, даже использование кэша представлений может быть недостаточным. В таких случаях мы рекомендуем рассмотреть метод денормализации. Разберем этот метод по шагам:

  1. Добавим в объект (справочник или документ) дополнительный строковый реквизит, например, ПредставлениеДляСписков.
  2. В модуле объекта в событии ПередЗаписью пропишем логику формирования этого строкового значения.
  3. В обработчике ОбработкаПолученияПолейПредставления укажем только этот новый реквизит.
  4. В ОбработкаПолученияПредставления просто присвоим параметру Представление значение этого реквизита.

Этот метод исключает любые вычисления «на лету» при отображении данных. Строка уже готова и лежит в той же таблице базы данных. Это самый быстрый способ из возможных, хотя он и требует дополнительного места на диске и аккуратности при обновлении данных (нужно переподтянуть значения, если изменился связанный объект SpaceTypesMain).

Использование модулей с повторным использованием значений

Проанализируем еще один способ оптимизации, упомянутый в обсуждении — использование модулей с повторным использованием (МПИ). Если алгоритм получения строкового значения сложный (например, требует анализа нескольких связанных регистров), вызов такой функции из ОбработкаПолученияПредставления может быть оправдан.

Выделим ключевые моменты работы с МПИ:

Однако помните: использование МПИ все равно медленнее, чем прямой доступ к реквизиту, уже полученному через ОбработкаПолученияПолейПредставления, так как вызов функции сам по себе несет накладные расходы.

Итоги и рекомендации

Подведем итог нашему исследованию производительности представлений в 1С:

  1. Никогда не используйте ОбщегоНазначения.ПолучитьЗначениеРеквизита или обращение «через точку» внутри обработчика получения представления. Это гарантированный путь к тормозам системы в списках.
  2. Всегда используйте ОбработкаПолученияПолейПредставления для предварительной выборки необходимых «плоских» реквизитов объекта.
  3. Для получения имен связанных объектов используйте стандартную функцию Строка(Ссылка), так как она максимально оптимизирована внутри платформы и использует кэш.
  4. Если быстродействия все равно не хватает — используйте денормализацию (хранение готовой строки представления в реквизите объекта).

Замер производительности не лукавит: он лишь подтверждает, что прямой запрос к базе данных всегда проигрывает грамотно настроенному механизму кэширования и предварительной выборки полей.

← На главную