К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как используется кэш объектов в 1С

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

Кэш объектов в 1С — это механизм, который позволяет не обращаться к базе данных повторно за одними и теми же данными, а хранить готовый результат в памяти сеанса. Чаще всего речь идёт об общих модулях с признаком «Повторное использование возвращаемых значений», но к этой же теме относятся кэш форм, кэш настроек и программное кэширование через параметры сеанса или соответствия.

Проблема, которую решает кэш, проста: типовые операции вроде получения текущего пользователя, константы, настройки учётной политики или реквизита справочника могут вызываться сотни раз за один сеанс. Каждое обращение к СУБД — это сетевой вызов, запрос и блокировочная нагрузка. Если результат известен и не меняется в течение вызова или сеанса, его разумно запомнить.

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

Что именно кэшируется в 1С и где хранится кэш

В платформе 1С:Предприятие 8 кэширование существует на нескольких уровнях. Первый уровень — платформенный: кластер серверов кэширует метаданные, сеансовые данные и результаты некоторых операций без участия разработчика. Второй уровень — прикладной: общие модули с повторным использованием значений, параметры сеанса, реквизиты форм и переменные модулей, куда разработчик складывает вычисленные значения.

Физически серверный кэш хранится в памяти рабочих процессов кластера, клиентский — в памяти клиентского приложения. Это принципиально: данные, закэшированные в клиентском вызове, недоступны на сервере и наоборот. При файловом режиме работы кэш живёт внутри процесса клиентского приложения.

Отдельно стоит упомянуть кэш метаданных и кэш СУБД: SQL Server или PostgreSQL тоже кэшируют результаты запросов и планы выполнения. Когда разработчик говорит «очистить кэш 1С», под этим могут скрываться совершенно разные действия — от перезапуска сеанса до очистки служебных каталогов.

Модули с повторным использованием значений: основной инструмент

Главный штатный механизм кэширования — свойство общего модуля «Повторное использование возвращаемых значений». Оно имеет три варианта: «Не использовать», «На время вызова» и «На время сеанса». Настройка выполняется в конфигураторе, в палитре свойств общего модуля.

Режим «На время вызова» означает, что результат функции запоминается в пределах одного обращения к серверу (одного серверного вызова). Как только вызов завершён, кэш сбрасывается. Этот режим безопасен: риск получить устаревшие данные минимален, а выигрыш появляется, когда одна и та же функция вызывается многократно внутри одной операции — например, при проведении документа с большим числом строк.

Режим «На время сеанса» хранит результат до конца сеанса пользователя. Он даёт максимальный выигрыш, но требует строгого отбора данных: кэшировать так можно только то, что гарантированно не изменится в течение сеанса либо чьё устаревание некритично. Типовые кандидаты — функциональные опции, константы, настройки, состав планов обмена.

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

Как включить кэширование функции
  1. 1
    Создайте общий модуль или откройте существующий, например НастройкиПовтИсп.
  2. 2
    В свойствах модуля установите «Повторное использование возвращаемых значений» = «На время вызова» или «На время сеанса».
  3. 3
    Установите флажок «Сервер» (и «Вызов сервера», если функции будут вызываться с клиента).
  4. 4
    Перенесите в модуль функции, возвращающие медленно меняющиеся данные, с параметрами простых типов.
  5. 5
    Проверьте в замере производительности, что повторные вызовы перестали выполнять запросы к базе.

Типичные сценарии применения кэша

Настройки и константы

Классический пример — функция вида ПолучитьЗначениеКонстанты(ИмяКонстанты) или ПолучитьФункциональнуюОпцию(Имя). В типовых конфигурациях для этого существуют модули с постфиксом «ПовтИсп»: например, обращение к функциональным опциям идёт через кэш, чтобы не читать константы при каждой проверке. Если вы пишете собственные проверки настроек, размещайте их именно в таких модулях.

Реквизиты справочников

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

Вычисляемые данные текущего сеанса

Текущий пользователь, его подразделение, права доступа, персональные настройки — данные, которые запрашиваются постоянно и меняются редко. Их принято кэшировать на время сеанса. При смене настроек администратором пользователю достаточно перезайти в сеанс, чтобы получить актуальные значения, — это приемлемая цена за скорость.

Сравнение режимов кэширования

На время вызова

Подходит для данных, читаемых многократно внутри одной операции: реквизиты ссылок при проведении, параметры в длинных циклах. Безопасен, кэш живёт секунды.

На время сеанса

Подходит для констант, функциональных опций, настроек пользователя. Максимальный выигрыш, но устаревшие данные сохраняются до конца сеанса.

Ручное кэширование (Соответствие в переменной модуля)

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

Программное кэширование и сброс кэша

Иногда штатных режимов недостаточно — например, нужно кэшировать результат с возможностью принудительного сброса. Тогда используют переменные модуля: функция проверяет, заполнено ли значение, и если нет — вычисляет и запоминает. Для коллекций значений применяют Соответствие, где ключ — ссылка или строковый идентификатор.

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

Учтите: метод сбрасывает кэш только текущего сеанса. Если настройку изменил один пользователь, остальные сеансы продолжат работать со старыми значениями до своего перезапуска. В многопользовательской системе это нужно учитывать при проектировании: либо принять задержку обновления, либо не кэшировать такие данные на время сеанса.

bsl
// Общий модуль с повторным использованием "На время вызова"
Функция СтавкаНДСНоменклатуры(Номенклатура) Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ СтавкаНДС ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка";
    Запрос.УстановитьПараметр("Ссылка", Номенклатура);
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.СтавкаНДС;
    КонецЕсли;
    Возврат Неопределено;
КонецФункции

// Сброс кэша после изменения настроек
ОбновитьПовторноИспользуемыеЗначения();

Типичные ошибки и риски при работе с кэшем

Самая частая ошибка — кэширование данных, которые меняются внутри той же транзакции. Например, функция возвращает остаток по складу, её поместили в модуль «На время вызова», а в рамках одного серверного вызова документ сначала записал движения, а потом снова запросил остаток — и получил старое значение. Результат: некорректный контроль остатков и ошибки в учёте.

Вторая группа ошибок связана с клиент-серверной архитектурой. Модуль с повторным использованием, доступный и на клиенте, и на сервере, фактически имеет два независимых кэша. Если логика рассчитывает, что клиент «увидит» значение, закэшированное на сервере, поведение будет непредсказуемым.

Третья проблема — кэширование объектов, а не значений. Функции с повторным использованием должны возвращать простые типы или ссылки. Возврат изменяемых объектов (скажем, построенного объекта СправочникОбъект) приведёт к тому, что все вызывающие получат один и тот же экземпляр, и изменения в одном месте «протекут» в другие.

Типичные ошибки
01
Кэширование остатков и итогов регистров — данные устаревают внутри транзакции, контроль работает неверно.
02
Передача сложных параметров (таблиц, структур с объектами) — платформа не сравнивает их корректно, кэш не срабатывает или срабатывает непредсказуемо.
03
Кэш «На время сеанса» для настроек, которые администратор меняет в рабочее время, — пользователи видят старые значения до перезахода.
04
Возврат изменяемых объектов из кэшируемой функции — общий экземпляр портится первым же вызывающим кодом.
05
Ожидание, что ОбновитьПовторноИспользуемыеЗначения() сбросит кэш у всех пользователей — метод действует только в текущем сеансе.

Как проверить, что кэш работает, и диагностировать проблемы

Убедиться в эффекте кэширования можно двумя способами. Первый — замер производительности в конфигураторе (Отладка → Замер производительности): после включения повторного использования количество вызовов кэшируемой функции в замере сократится, хотя обращений к ней в коде столько же. Второй — технологический журнал с отбором по событиям DBMSSQL или DBPOSTGRS: повторные запросы к кэшируемым таблицам должны исчезнуть.

Если подозреваете, что проблема вызвана устаревшим кэшем, выполните простую диагностику: перезапустите сеанс пользователя. Если поведение изменилось — с высокой вероятностью виноват кэш «На время сеанса». Если нет — ищите причину в данных или коде.

Для кэша «На время вызова» диагностика сложнее: устаревание проявляется только внутри одной операции. Признак — функция возвращает значение, которое не соответствует только что записанным данным. Лечение — убрать кэширование для этой функции или перенести чтение после окончания изменяющей операции.

Контрольные точки

Как проверить результат

Замер производительности после включения повторного использования
Норма

Количество выполнений кэшируемой функции в замере сократилось

Тревожный признак

Функция выполняется при каждом обращении — проверьте свойство модуля и типы параметров

Поведение после перезапуска сеанса
Норма

Данные корректны и до, и после перезапуска

Тревожный признак

После перезапуска значения меняются — кэш сеанса хранит устаревшие данные

Чтение данных после их записи в той же операции
Норма

Возвращаются свежие значения

Тревожный признак

Возвращаются значения до изменения — функцию нельзя кэшировать

Когда кэш использовать нельзя и какие есть альтернативы

Не кэшируйте: остатки и обороты регистров, данные, участвующие в контроле внутри транзакции, результаты запросов с отбором по быстро меняющимся параметрам, любые данные, чьё устаревание хотя бы на секунды недопустимо по логике учёта. Также бессмысленно кэшировать функции, вызываемые один-два раза за операцию, — выигрыша не будет, а сложность добавится.

Альтернативы кэшу, которые часто решают задачу лучше: получение всех нужных данных одним пакетным запросом до цикла; передача уже выбранных данных через параметры процедур; использование временных таблиц в менеджере временных таблиц для повторно используемых выборок внутри одного запроса. Эти приёмы не создают проблемы устаревания и проще в отладке.

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

Маршрут решения

Как выбрать подход

Данные — константа, функциональная опция, настройка, меняющаяся редкоМодуль с повторным использованием «На время сеанса»
Данные читаются многократно внутри одной операции, но могут меняться между операциямиРежим «На время вызова» или однократное чтение в переменную в начале операции
Нужны реквизиты множества разных ссылок в циклеОдин запрос с соединением до цикла вместо кэша
Данные участвуют в контроле внутри транзакцииНикакого кэша — только прямое чтение, при необходимости с блокировкой

Частые вопросы

Чем отличаются режимы «На время вызова» и «На время сеанса»?

Первый хранит результат только в пределах одного серверного вызова и сбрасывается автоматически — он безопаснее. Второй хранит значение до конца сеанса пользователя, даёт больший выигрыш, но требует гарантии, что данные не устареют за это время.

Как сбросить кэш повторно используемых значений?

Вызовите встроенный метод ОбновитьПовторноИспользуемыеЗначения() — он очистит кэш всех таких модулей в текущем сеансе. На другие сеансы пользователей это не влияет: им потребуется перезайти или дождаться собственного сброса.

Почему кэшируемая функция всё равно выполняется каждый раз?

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

Можно ли кэшировать остатки товаров для ускорения проведения?

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

Работает ли кэш одинаково на клиенте и на сервере?

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

Что делать, если после изменения настройки пользователи видят старое значение?

Это типичный признак кэша «На время сеанса». Варианты: вызывать ОбновитьПовторноИспользуемыеЗначения() после записи настройки, попросить пользователей перезайти в сеанс или перевести функцию на режим «На время вызова», если настройка меняется в рабочее время.

Итог

Что важно запомнить

Кэш объектов в 1С строится на общих модулях с повторным использованием значений: «На время вызова» — безопасный режим для многократных чтений внутри операции, «На время сеанса» — для констант и настроек. Никогда не кэшируйте остатки и данные, меняющиеся в транзакции. Проверяйте эффект замером производительности, а устаревание диагностируйте перезапуском сеанса.