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