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