В практике разработки на платформе 1С:Предприятие 8 часто возникает дилемма: как эффективнее проверить, соответствует ли конкретный элемент справочника определенному коду. На первый взгляд, задача кажется тривиальной, но за ней скрываются глубокие механизмы работы объектного кэша, трансляции запросов в SQL и принципы архитектурной чистоты кода. Рассмотрим ситуацию, когда у нас есть два варианта написания условия:
Вариант 1 (Поиск ссылки):
Если НужнаяНомен = Справочники.Номенклатура.НайтиПоКоду("ЦБ0025637") Тогда
// Действие
КонецЕсли;
Вариант 2 (Обращение к реквизиту):
Если НужнаяНомен.Код = "ЦБ0025637" Тогда
// Действие
КонецЕсли;
Разберем детально каждый из них, чтобы выяснить, какой метод быстрее и, что более важно, какой из них является корректным с точки зрения платформенных стандартов.
Метод НайтиПоКоду() является стандартным способом получения ссылки на элемент справочника по его строковому идентификатору. Проанализируем, что происходит "под капотом" платформы при выполнении этой строки:
Номенклатура.WHERE по полю Code.Ссылка (GUID).Важным нюансом является то, что НайтиПоКоду() возвращает только ссылку. Платформа не вычитывает из базы данных другие реквизиты (наименование, артикул, склад и т.д.), что делает этот вызов "легким" для сети и оперативной памяти.
Теперь рассмотрим конструкцию НужнаяНомен.Код. Здесь ситуация кардинально меняется в зависимости от того, в каком состоянии находится переменная НужнаяНомен.
Если НужнаяНомен — это Ссылка, то при первом обращении к любому ее реквизиту через точку срабатывает механизм разыменования. Платформа видит, что данных кода в памяти нет, и отправляется в базу данных. Но, в отличие от специализированного поиска, она выполняет запрос SELECT *. Это означает, что даже если вам нужен только "Код", 1С получит из базы все данные объекта. Если у номенклатуры 50 реквизитов и несколько огромных текстовых полей, это будет крайне неэффективно.
Однако, если объект уже находится в объектном кэше (например, вы только что получили его или обращались к другим его реквизитам ранее), то обращение через точку произойдет мгновенно, так как данные будут взяты из оперативной памяти сервера или клиента.
Проанализируем ситуацию с точки зрения замеров производительности:
Важно помнить про объем данных. В цикле по тысячам элементов постоянное разыменование ссылок, которые не попадают в кэш, может привести к катастрофическому падению производительности. Кэш 1С имеет ограниченный объем (около 20 Мб), и при переборе большого массива данных старые объекты будут вытесняться новыми, заставляя платформу снова и снова делать SELECT *.
Выясним причину, почему вариант с НайтиПоКоду() может быть опасен. В 1С уникальность кодов может быть настроена по-разному: во всем справочнике или в пределах подчинения (в папках). Если уникальность не гарантирована или была нарушена при некорректном обмене данными, метод НайтиПоКоду() вернет первый попавшийся элемент. Если в базе два товара с кодом "ЦБ0025637", условие может не сработать для второго товара, даже если его код совпадает, так как ссылки будут разными.
В то же время, сравнение НужнаяНомен.Код = "..." всегда проверяет именно строковое значение кода конкретной ссылки, что в данном контексте выглядит более надежным, но менее производительным при отсутствии кэширования.
Если мы хотим добиться максимальной производительности, особенно в циклах, нам следует отказаться от обоих вариантов в пользу Запроса. Посмотрим на пример того, как это должно выглядеть профессионально:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Код = &НужныйКод";
Запрос.УстановитьПараметр("НужныйКод", "ЦБ0025637");
РезультатЗапроса = Запрос.Выполнить();
// Далее работаем с результатом
Запрос работает напрямую с таблицами СУБД, использует индексы и не тянет за собой лишние данные объекта. Это "золотой стандарт" разработки на 1С.
Посмотрим на ситуацию шире. Использование "жестко зашитых" кодов в тексте программы (так называемые магические строки) — это признак плохого тона в программировании. Код элемента может измениться при перенумерации, префикс может поменяться при смене узла обмена, и ваша логика "сломается".
Рассмотрим альтернативы:
Справочники.Номенклатура.ИмяПредопределенного. Это максимально быстро и надежно.Подведем итог нашему исследованию:
1. Используйте обращение через точку (Вариант 2), если вы точно знаете, что объект уже находится в памяти (например, внутри модуля объекта или если вы ранее уже читали данные этой ссылки).
2. Используйте НайтиПоКоду() (Вариант 1) только для разовых операций в интерактивных формах, где критична скорость написания кода, а не производительность системы под нагрузкой.
3. Используйте Запросы, если вам нужно обработать массив данных или выполнить проверку в цикле.
4. Старайтесь избегать привязки к текстовым кодам. Предопределенные элементы — лучший способ связи программной логики с данными справочников.
Помните, что погоня за миллиардными долями секунды в 1С часто бессмысленна, если в другом месте выполняется неоптимальный запрос в цикле. Всегда делайте замер производительности в реальных условиях работы базы.