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