Делает ли метод УникальныйИдентификатор() запрос к базе данных в 1С?

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

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

Внутреннее устройство ссылки и работа метода в оперативной памяти

Рассмотрим, как устроена ссылка в платформе 1С. Любая ссылка (например, СправочникСсылка, ДокументСсылка и т. д.) представляет собой составную структуру в памяти, состоящую из идентификатора таблицы метаданных и 16-байтного двоистого значения GUID (уникального идентификатора записи).

Когда мы вызываем метод Ссылка.УникальныйИдентификатор(), платформа не выполняет никаких запросов к базе данных. Извлечение значения происходит исключительно в оперативной памяти текущего сеанса. Более того, доступность этого метода охватывает тонкий клиент, веб-клиент, мобильные клиенты и сервер. Это означает, что если ссылка уже передана на клиент, вызов УникальныйИдентификатор() на клиенте даже не инициирует сетевой вызов к серверу 1С — GUID считывается из локального контекста ссылки в памяти клиентского приложения.

Распространенная ошибка: получение объекта ради идентификатора

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


// Неправильный подход, создающий критическую нагрузку на СУБД:
ГУИД = Ссылка.ПолучитьОбъект().УникальныйИдентификатор();

Проанализируем, к чему приводит такой вызов. Метод ПолучитьОбъект() выполняет полноценное считывание данных записи из таблицы СУБД, включая все реквизиты шапки и строки всех табличных частей. Если выполнять такой код в цикле по массиву или таблице ссылок, производительность упадет в сотни раз из-за избыточных дисковых и сетевых операций базы данных.

Всегда обращаемся к методу напрямую от ссылки:


// Правильный подход: выполняется мгновенно без запросов к СУБД
ГУИД = Ссылка.УникальныйИдентификатор();

Быстрое получение строкового GUID: метод XMLСтрока

Часто уникальный идентификатор требуется не в виде объекта типа УникальныйИдентификатор, а в виде стандартной строки из 36 символов (например, для обмена данными или сравнения с внешними таблицами). Классический вариант преобразования выглядит следующим образом:

СтрокаГУИД = Строка(Ссылка.УникальныйИдентификатор());

Однако в платформе предусмотрен более производительный механизм — системная функция XMLСтрока(). Посмотрим, как ее использовать:

СтрокаГУИД = XMLСтрока(Ссылка);

Вызов XMLСтрока(Ссылка) работает быстрее цепочки со Строка(), поскольку платформа сразу возвращает каноническую строку сериализации ссылки (ее GUID), минуя этап создания промежуточного объекта типа УникальныйИдентификатор в управляемой куче памяти.

Эффективное сопоставление таблиц со ссылками и строковыми GUID

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

  1. Восстановление ссылки без обращения к базе данных.

    Метод менеджера объекта ПолучитьСсылку() принимает объект УникальныйИдентификатор и возвращает ссылку в памяти. При этом он также не делает запросов к базе данных и не проверяет физическое наличие записи в таблице. Мы можем восстановить ссылки для второй таблицы и выполнить пакетное соединение в запросе по индексированному полю ссылки:

    
    ТаблицаСГУИД.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    
    Для Каждого Стр Из ТаблицаСГУИД Цикл
        УИД = Новый УникальныйИдентификатор(Стр.СтрокаГУИД);
        Стр.Ссылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);
    КонецЦикла;
    
    // Теперь обе таблицы можно передать в Запрос и связать через ВНУТРЕННЕЕ СОЕДИНЕНИЕ по полю Ссылка
    
  2. Использование функции языка запросов (начиная с версии 8.3.22).

    Начиная с версии платформы 8.3.22, в языке запросов 1С появилась встроенная функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка). Она позволяет извлекать идентификатор непосредственно в запросе. Однако обратим внимание: функция возвращает не строку, а значение типа УникальныйИдентификатор. Поэтому во входящей таблице колонка со значениями должна быть предварительно типизирована соответствующим образом:

    
    // В таблице значений типизируем колонку как УникальныйИдентификатор
    ТаблицаСГУИД.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("УникальныйИдентификатор"));
    
    Для Каждого Стр Из ТаблицаСГУИД Цикл
        Стр.Идентификатор = Новый УникальныйИдентификатор(Стр.СтрокаГУИД);
    КонецЦикла;
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Т1.Ссылка КАК Ссылка,
        |    УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Т1.Ссылка) КАК УИД
        |ПОМЕСТИТЬ ВТ_Ссылки
        |ИЗ
        |    &ТаблицаСсылок КАК Т1
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    Т1.Ссылка КАК Ссылка,
        |    Т2.Идентификатор КАК Идентификатор
        |ИЗ
        |    ВТ_Ссылки КАК Т1
        |    ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТаблицаСГУИД КАК Т2
        |        ПО Т1.УИД = Т2.Идентификатор";
    

Таким образом, операция получения уникального идентификатора из ссылки является безопасной с точки зрения производительности СУБД, так как выполняется целиком в оперативной памяти без дополнительных обращений к серверу баз данных.

← На главную