Что быстрее и корректнее: НайтиПоКоду() или сравнение через точку НужнаяНомен.Код?

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

В практике разработки на платформе 1С:Предприятие 8 часто возникает дилемма: как эффективнее проверить, соответствует ли конкретный элемент справочника определенному коду. На первый взгляд, задача кажется тривиальной, но за ней скрываются глубокие механизмы работы объектного кэша, трансляции запросов в SQL и принципы архитектурной чистоты кода. Рассмотрим ситуацию, когда у нас есть два варианта написания условия:

Вариант 1 (Поиск ссылки):


Если НужнаяНомен = Справочники.Номенклатура.НайтиПоКоду("ЦБ0025637") Тогда 
    // Действие
КонецЕсли;

Вариант 2 (Обращение к реквизиту):


Если НужнаяНомен.Код = "ЦБ0025637" Тогда 
    // Действие
КонецЕсли;

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

Анализ варианта 1: Использование метода НайтиПоКоду()

Метод НайтиПоКоду() является стандартным способом получения ссылки на элемент справочника по его строковому идентификатору. Проанализируем, что происходит "под капотом" платформы при выполнении этой строки:

  1. Платформа формирует SQL-запрос к таблице справочника Номенклатура.
  2. В запросе используется условие WHERE по полю Code.
  3. Поскольку поле Код в типовых конфигурациях всегда индексировано, поиск происходит максимально быстро средствами СУБД.
  4. Результатом метода является Ссылка (GUID).
  5. В условии происходит сравнение двух ссылок (двух уникальных идентификаторов). Сравнение простых типов (GUID) выполняется процессором мгновенно.

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

Анализ варианта 2: Разыменование ссылки через точку

Теперь рассмотрим конструкцию НужнаяНомен.Код. Здесь ситуация кардинально меняется в зависимости от того, в каком состоянии находится переменная НужнаяНомен.

Если НужнаяНомен — это Ссылка, то при первом обращении к любому ее реквизиту через точку срабатывает механизм разыменования. Платформа видит, что данных кода в памяти нет, и отправляется в базу данных. Но, в отличие от специализированного поиска, она выполняет запрос SELECT *. Это означает, что даже если вам нужен только "Код", 1С получит из базы все данные объекта. Если у номенклатуры 50 реквизитов и несколько огромных текстовых полей, это будет крайне неэффективно.

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

Сравнение производительности: Миллисекунды и логика

Проанализируем ситуацию с точки зрения замеров производительности:

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

Вопрос корректности и уникальности

Выясним причину, почему вариант с НайтиПоКоду() может быть опасен. В 1С уникальность кодов может быть настроена по-разному: во всем справочнике или в пределах подчинения (в папках). Если уникальность не гарантирована или была нарушена при некорректном обмене данными, метод НайтиПоКоду() вернет первый попавшийся элемент. Если в базе два товара с кодом "ЦБ0025637", условие может не сработать для второго товара, даже если его код совпадает, так как ссылки будут разными.

В то же время, сравнение НужнаяНомен.Код = "..." всегда проверяет именно строковое значение кода конкретной ссылки, что в данном контексте выглядит более надежным, но менее производительным при отсутствии кэширования.

Оптимальное решение: Использование запросов

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


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

Запрос.УстановитьПараметр("НужныйКод", "ЦБ0025637");
РезультатЗапроса = Запрос.Выполнить();
// Далее работаем с результатом

Запрос работает напрямую с таблицами СУБД, использует индексы и не тянет за собой лишние данные объекта. Это "золотой стандарт" разработки на 1С.

Архитектурный аспект: "Магические строки"

Посмотрим на ситуацию шире. Использование "жестко зашитых" кодов в тексте программы (так называемые магические строки) — это признак плохого тона в программировании. Код элемента может измениться при перенумерации, префикс может поменяться при смене узла обмена, и ваша логика "сломается".

Рассмотрим альтернативы:

  1. Предопределенные элементы: Если эта номенклатура системная, создайте её в конфигураторе как предопределенную. Тогда обращение будет выглядеть так: Справочники.Номенклатура.ИмяПредопределенного. Это максимально быстро и надежно.
  2. Дополнительные реквизиты или настройки: Создайте константу или параметр учета, где пользователь сам выберет нужную номенклатуру.

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

Подведем итог нашему исследованию:

1. Используйте обращение через точку (Вариант 2), если вы точно знаете, что объект уже находится в памяти (например, внутри модуля объекта или если вы ранее уже читали данные этой ссылки).

2. Используйте НайтиПоКоду() (Вариант 1) только для разовых операций в интерактивных формах, где критична скорость написания кода, а не производительность системы под нагрузкой.

3. Используйте Запросы, если вам нужно обработать массив данных или выполнить проверку в цикле.

4. Старайтесь избегать привязки к текстовым кодам. Предопределенные элементы — лучший способ связи программной логики с данными справочников.

Помните, что погоня за миллиардными долями секунды в 1С часто бессмысленна, если в другом месте выполняется неоптимальный запрос в цикле. Всегда делайте замер производительности в реальных условиях работы базы.

← На главную