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