Происходит ли обращение к БД при работе с реквизитами объекта через ссылку?

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает дилемма: как правильнее и быстрее получить значение реквизита объекта — через обращение к ссылке (Ссылка.Реквизит), через получение объекта (Ссылка.ПолучитьОбъект().Реквизит) или с помощью запроса? Вопрос не ограничивается только удобством написания кода, он напрямую затрагивает производительность системы и актуальность получаемых данных. Разберем детально, как устроены внутренние механизмы платформы при работе с данными.

Механизм объектного кэша: как 1С экономит ресурсы

Для оптимизации работы платформа использует так называемый объектный кэш. Когда мы впервые обращаемся к любому реквизиту объекта через его ссылку (например, Ссылка.Наименование), платформа выполняет запрос к базе данных. Однако важно понимать, что считывается не только запрашиваемый реквизит, а весь объект целиком, включая все его реквизиты и табличные части (за исключением некоторых тяжелых полей типа ХранилищеЗначения).

Проанализируем алгоритм работы этого механизма:

  1. При первом обращении данные считываются из СУБД и помещаются в оперативную память (кэш сеанса).
  2. При последующих обращениях к этому же реквизиту или другим реквизитам того же объекта (например, Ссылка.Дата), данные берутся уже из кэша, и повторного обращения к базе данных не происходит.
  3. Это значительно ускоряет работу, если в коде часто используются разные поля одного и того же объекта.

Правило 20 секунд и актуальность данных

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

Согласно механизмам платформы, данные в объектном кэше считаются безусловно валидными (верными) в течение 20 секунд. Это означает, что если между первым и вторым обращением к реквизиту прошло менее 20 секунд, платформа даже не будет проверять базу данных — она просто отдаст старое значение из памяти. Если же интервал превысил 20 секунд, платформа выполнит легкий запрос к БД, чтобы проверить версию объекта (поле _Version). Если версия совпала, данные в кэше снова считаются валидными. Если нет — объект перечитывается полностью.

Важный вывод: Обращение через ссылку может вернуть неактуальные данные, если объект был изменен в другом сеансе менее 20 секунд назад. Это критично для бизнес-логики, требующей мгновенной синхронизации.

Работа через объект и метод Прочитать()

Если мы работаем с переменной типа ДокументОбъект или СправочникОбъект, ситуация меняется. Переменная-объект — это фактически слепок данных в оперативной памяти. Если мы изменили реквизит объекта в коде, но не записали его, то при обращении к Объект.Реквизит мы получим новое (еще не записанное) значение. Данные из базы в этом случае не перечитываются.

Чтобы гарантированно получить актуальные данные из базы в переменную объекта, необходимо использовать метод Прочитать():


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

Использование запросов — самый быстрый путь

Несмотря на наличие кэша, самым производительным и надежным способом получения данных считается запрос. Рассмотрим причины, почему это так:

  1. Отсутствие избыточности: Запрос позволяет выбрать только нужные поля (например, только СуммаДокумента), в то время как обращение через ссылку всегда тянет из базы весь объект со всеми табличными частями.
  2. Актуальность: Запрос всегда обращается напрямую к таблицам СУБД (с учетом текущего уровня изоляции транзакций) и не зависит от 20-секундного интервала объектного кэша.
  3. Экономия памяти: Объектный кэш может переполняться и вытесняться, если объектов много. Запросы же не засоряют кэш тяжелыми данными.

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


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

Запрос.УстановитьПараметр("Ссылка", НужнаяСсылка);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Следующий() Тогда
    ТекущаяСумма = Результат.Сумма;
КонецЕсли;

Транзакционный кэш

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

Резюме и рекомендации

Подведем итоги нашего анализа и выделим лучшие практики работы с реквизитами в 1С:

Понимание этих нюансов позволяет писать не только функциональный, но и высокопроизводительный код, который не будет "тормозить" систему при росте объема данных.

← На главную