Как правильнее и быстрее получить реквизит по ссылке в 1С: через точку, запросом или с помощью БСП?

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

В процессе разработки на платформе 1С:Предприятие 8 перед каждым программистом регулярно встает выбор: как получить значение реквизита, имея на руках только ссылку на объект? Существует три основных подхода: обращение «через точку» (Ссылка.ИмяРеквизита), написание прямого запроса к базе данных или использование стандартных функций библиотеки стандартных подсистем (БСП). В этой статье мы подробно разберем, какой метод эффективнее в разных ситуациях, проанализируем механизмы работы платформы и выясним, как избежать типичных ошибок производительности.

Вариант 1: Обращение через точку (Чтение свойства ссылки)

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


Идентификатор = Узел.Идентификатор;

Проанализируем, что происходит «под капотом» платформы при выполнении этой строки кода. Когда мы обращаемся к реквизиту через точку, система выполняет следующие действия:

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

Преимущества:

Недостатки:

Вариант 2: Получение данных через запрос

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Т.Идентификатор КАК Идентификатор
    |ИЗ
    |   ПланОбмена.усОбменПоWebСервису КАК Т
    |ГДЕ
    |   Т.Ссылка = &Узел";

Запрос.УстановитьПараметр("Узел", СсылкаНаУзел);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    Идентификатор = Выборка.Идентификатор;
КонецЕсли;

Иногда, чтобы использовать конструктор запроса при работе с обобщенными ссылками, применяют конструкцию ВЫРАЗИТЬ:


"ВЫБРАТЬ ВЫРАЗИТЬ(&Узел КАК ПланОбмена.усОбменПоWebСервису).Идентификатор"

Проанализируем ситуацию: в отличие от обращения через точку, запрос заставляет SQL-сервер вернуть только одну конкретную колонку. Это минимизирует трафик между сервером приложений и СУБД.

Когда стоит выбирать запрос:

  1. Когда вам нужно получить данные один раз и вы точно знаете, что другие реквизиты этого объекта в текущем алгоритме не потребуются.
  2. В циклах. Это критически важно! Никогда не используйте точку в цикле при обходе ссылок (например, при обработке строк результата другого запроса). Это порождает проблему «N+1 запрос», когда на каждую итерацию цикла выполняется отдельное тяжелое чтение из базы.
  3. При работе с объектами, содержащими большое количество данных.

Вариант 3: Использование функций БСП

Выясним причину популярности функций библиотеки стандартных подсистем. Многие опытные разработчики предпочитают использовать ОбщегоНазначения.ЗначениеРеквизитаОбъекта().


Идентификатор = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Узел, "Идентификатор");

Рассмотрим подробнее, почему это удобно:

Сравнение производительности: Точка vs Запрос

Посмотрим на практические рекомендации. Существует тонкий момент с кэшированием. Если вы в цикле миллион раз обращаетесь к одной и той же ссылке, то обращение через точку сработает быстрее, так как объект один раз попадет в кэш и все последующие обращения будут идти к оперативной памяти.

Однако, если вы перебираете миллион разных ссылок, обращение через точку «убьет» производительность системы. В этом случае правильным решением будет:

  1. Выбрать все необходимые данные одним запросом заранее.
  2. Поместить их во временную таблицу или прочитать в таблицу значений (массив структур).
  3. Работать с локальной выборкой.

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

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

Подведем итог нашему анализу и сформулируем правила выбора метода:

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

Соблюдение этих простых правил позволит вашим разработкам работать быстро и стабильно даже при значительном росте объема данных в информационной базе.

← На главную