Сколько обращений к базе данных генерирует запрос 1С при выборе ссылки и реквизитов?

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

При оптимизации производительности и подготовке к техническим собеседованиям программисты 1С часто сталкиваются с вопросом: сколько реальных SQL-запросов уходит на сервер СУБД при выполнении вроде бы простого запроса к платформе. Рассмотрим классическую задачу и подробно проанализируем, как платформа «1С:Предприятие» взаимодействует с базой данных на уровне SQL Profiler.

Исходные условия задачи

Рассмотрим следующий фрагмент кода 1С:


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

Запрос.УстановитьПараметр("КодКарты", "КакойТоТамКодСтрокой");

На первый взгляд кажется, что здесь выполняется ровно 1 SQL-запрос. Однако если запустить трассировщик СУБД (например, MS SQL Server Profiler), результат может сильно урезать ожидание. Выясним причину такого поведения и разберем все сценарии по шагам.

Сценарий 1. Отсутствие вызова метода Выполнить()

Проанализируем приведенный код предельно внимательно. В представленном фрагменте присутствуют только создание объекта Запрос, установка текста и передача параметра Запрос.УстановитьПараметр.

В архитектуре 1С создание запроса и передача параметров происходят исключительно в оперативной памяти сервера приложений. Никаких вызовов к серверу базы данных в этот момент не происходит. Обращение к СУБД отправляется только тогда, когда вызывается метод Запрос.Выполнить() или Запрос.ВыполнитьПакет().

Итог: Если код исполняется строго в том виде, как написано (без вызова Выполнить()), то количество обращений к базе данных будет равно 0.

Сценарий 2. Запрос выполняет выборку конкретного реквизита (без ссылки)

Посмотрим на ситуацию, когда метод Запрос.Выполнить() вызван, но в секции ВЫБРАТЬ указывается примитивный реквизит (например, строковый код или наименование), а не ссылка:


ВЫБРАТЬ ПЕРВЫЕ 1
    СкидочныеКарты.КодКарты КАК КодКарты
ИЗ
    Справочник.СкидочныеКарты КАК СкидочныеКарты
ГДЕ
    СкидочныеКарты.КодКарты = &КодКарты

В этом случае платформа 1С транслирует текст в один-единственный вызов хранимой процедуры sp_executesql:


exec sp_executesql N'SELECT TOP 1
T1._Fld11
FROM dbo._Reference10 T1
WHERE (T1._Fld11 = P1)',N'P1 nvarchar(4000)',N'КакойТоТамКодСтрокой'

СУБД возвращает только запрошенную колонку, платформе не требуется подгружать дополнительную информацию об объекте. В трассировщике мы зафиксируем ровно 1 запрос.

Сценарий 3. Запрос выбирает поле Ссылка и задействует кэш объектов

Теперь разберем основной случай, когда в запросе выбирается поле СкидочныеКарты.Ссылка. При выборе ссылки платформа 1С включает механизм объектного кэширования сеанса.

Если объект еще не находится в кэше сеанса, при выполнении запроса и считывании результатов платформа выполняет следующие шаги:

  1. Основной запрос выборки: Платформа запрашивает уникальный идентификатор ссылки _IDRRef из таблицы справочника:
    
    exec sp_executesql N'SELECT TOP 1
    T1._IDRRef
    FROM dbo._Reference10 T1
    WHERE (T1._Fld11 = P1)',N'P1 nvarchar(4000)',N'КакойТоТамКодСтрокой'
    
  2. Запрос проверки версии данных: Чтобы поместить найденный объект в кэш и убедиться в его актуальности, платформа отправляет второй запрос для считывания поля версии _Version:
    
    exec sp_executesql N'SELECT
    T1._Version
    FROM dbo._Reference10 T1
    WHERE T1._IDRRef = P1',N'P1 varbinary(16)',0x8488AC220BDA918F11E82FF8E1A9F1C6
    
  3. Запрос считывания реквизитов объекта: Платформа автоматически считывает остальные поля объекта (код, наименование, пометку удаления, предопределенность), чтобы полностью сформировать объектный кэш:
    
    exec sp_executesql N'SELECT
    T2._IDRRef,
    T2._Version,
    T2._Marked,
    T2._PredefinedID,
    T2._Code,
    T2._Description,
    T2._Fld11
    FROM dbo._Reference10 T2
    WHERE T2._IDRRef = P1 AND T2._Version <> @P2',N'P1 varbinary(16),@P2 varbinary(8000)',0x8488AC220BDA918F11E82FF8E1A9F1C6,0x00000000000007D1
    

Таким образом, при первичном обращении к объекту выборка поля Ссылка генерирует в профайлере от 2 до 3 запросов к СУБД. Если тот же объект выбирается повторно и уже присутствует в кэше сеанса, количество запросов снижается до 1.

Влияние дополнительного функционала и механизмов платформы

На количество запросов в профайлере также оказывают влияние дополнительные факторы:

1. Механизм RLS (Row Level Security): Если для объекта метаданных или роли текущего пользователя настроено ограничение доступа на уровне записей, платформа может предварять основной запрос служебными обращениями для выборки ключей доступа и формирования временных таблиц прав.

2. Транзакционный кэш: При исполнении кода внутри явной транзакции (между вызовами НачатьТранзакцию() и ЗафиксироватьТранзакцию()) или в обработчиках событий записи/проведения платформа использует транзакционный кэш, что предотвращает повторные служебные проверки версий данных.

Рекомендации по оптимизации запросов

Для повышения производительности высоконагруженных систем придерживайтесь простых правил:

← На главную