Разработка и Конфигурация · 13 мин
Как используется кэш объектов в 1С
Как используется кэш объектов в 1С: модули с повторным использованием значений, кэширование справочников и настроек, типичные ошибки и способы сброса кэша.
Кэш объектов в 1С — это механизм, который позволяет не обращаться к базе данных повторно за одними и теми же данными, а хранить готовый результат в памяти сеанса. Чаще всего речь идёт об общих модулях с признаком «Повторное использование возвращаемых значений», но к этой же теме относятся кэш форм, кэш настроек и программное кэширование через параметры сеанса или соответствия.
Проблема, которую решает кэш, проста: типовые операции вроде получения текущего пользователя, константы, настройки учётной политики или реквизита справочника могут вызываться сотни раз за один сеанс. Каждое обращение к СУБД — это сетевой вызов, запрос и блокировочная нагрузка. Если результат известен и не меняется в течение вызова или сеанса, его разумно запомнить.
При этом кэш — источник тонких ошибок: устаревшие значения, некорректное поведение при изменении данных в том же сеансе, различия между тонким клиентом и сервером. Поэтому важно понимать не только как включить кэширование, но и когда его применять нельзя.
Что именно кэшируется в 1С и где хранится кэш
В платформе 1С:Предприятие 8 кэширование существует на нескольких уровнях. Первый уровень — платформенный: кластер серверов кэширует метаданные, сеансовые данные и результаты некоторых операций без участия разработчика. Второй уровень — прикладной: общие модули с повторным использованием значений, параметры сеанса, реквизиты форм и переменные модулей, куда разработчик складывает вычисленные значения.
Физически серверный кэш хранится в памяти рабочих процессов кластера, клиентский — в памяти клиентского приложения. Это принципиально: данные, закэшированные в клиентском вызове, недоступны на сервере и наоборот. При файловом режиме работы кэш живёт внутри процесса клиентского приложения.
Отдельно стоит упомянуть кэш метаданных и кэш СУБД: SQL Server или PostgreSQL тоже кэшируют результаты запросов и планы выполнения. Когда разработчик говорит «очистить кэш 1С», под этим могут скрываться совершенно разные действия — от перезапуска сеанса до очистки служебных каталогов.
Модули с повторным использованием значений: основной инструмент
Главный штатный механизм кэширования — свойство общего модуля «Повторное использование возвращаемых значений». Оно имеет три варианта: «Не использовать», «На время вызова» и «На время сеанса». Настройка выполняется в конфигураторе, в палитре свойств общего модуля.
Режим «На время вызова» означает, что результат функции запоминается в пределах одного обращения к серверу (одного серверного вызова). Как только вызов завершён, кэш сбрасывается. Этот режим безопасен: риск получить устаревшие данные минимален, а выигрыш появляется, когда одна и та же функция вызывается многократно внутри одной операции — например, при проведении документа с большим числом строк.
Режим «На время сеанса» хранит результат до конца сеанса пользователя. Он даёт максимальный выигрыш, но требует строгого отбора данных: кэшировать так можно только то, что гарантированно не изменится в течение сеанса либо чьё устаревание некритично. Типовые кандидаты — функциональные опции, константы, настройки, состав планов обмена.
Важное ограничение: кэширование работает только для функций, не для процедур, и ключом кэша служит набор значений параметров. Если параметр — сложный объект (например, таблица значений), платформа не сможет корректно сравнить его с предыдущим вызовом, и кэш может работать не так, как ожидалось. Передавайте в кэшируемые функции простые типы: строки, числа, ссылки, даты.
- 1Создайте общий модуль или откройте существующий, например НастройкиПовтИсп.
- 2В свойствах модуля установите «Повторное использование возвращаемых значений» = «На время вызова» или «На время сеанса».
- 3Установите флажок «Сервер» (и «Вызов сервера», если функции будут вызываться с клиента).
- 4Перенесите в модуль функции, возвращающие медленно меняющиеся данные, с параметрами простых типов.
- 5Проверьте в замере производительности, что повторные вызовы перестали выполнять запросы к базе.
Типичные сценарии применения кэша
Настройки и константы
Классический пример — функция вида ПолучитьЗначениеКонстанты(ИмяКонстанты) или ПолучитьФункциональнуюОпцию(Имя). В типовых конфигурациях для этого существуют модули с постфиксом «ПовтИсп»: например, обращение к функциональным опциям идёт через кэш, чтобы не читать константы при каждой проверке. Если вы пишете собственные проверки настроек, размещайте их именно в таких модулях.
Реквизиты справочников
Частая ситуация — в цикле обработки строк документа нужно получить, например, ставку НДС номенклатуры или валюту договора. Обращение к реквизиту через точку в цикле порождает неявный запрос на каждой итерации. Правильные решения: либо получить все нужные реквизиты одним запросом до цикла, либо использовать кэширующую функцию ЗначениеРеквизитаОбъекта(Ссылка, ИмяРеквизита) из модуля с повторным использованием, если ссылки повторяются.
Вычисляемые данные текущего сеанса
Текущий пользователь, его подразделение, права доступа, персональные настройки — данные, которые запрашиваются постоянно и меняются редко. Их принято кэшировать на время сеанса. При смене настроек администратором пользователю достаточно перезайти в сеанс, чтобы получить актуальные значения, — это приемлемая цена за скорость.
Сравнение режимов кэширования
Подходит для данных, читаемых многократно внутри одной операции: реквизиты ссылок при проведении, параметры в длинных циклах. Безопасен, кэш живёт секунды.
Подходит для констант, функциональных опций, настроек пользователя. Максимальный выигрыш, но устаревшие данные сохраняются до конца сеанса.
Гибкий контроль ключей и сброса, но требует аккуратности: в клиент-серверном режиме переменные общего модуля живут отдельно на клиенте и сервере, легко получить рассинхронизацию.
Программное кэширование и сброс кэша
Иногда штатных режимов недостаточно — например, нужно кэшировать результат с возможностью принудительного сброса. Тогда используют переменные модуля: функция проверяет, заполнено ли значение, и если нет — вычисляет и запоминает. Для коллекций значений применяют Соответствие, где ключ — ссылка или строковый идентификатор.
Для принудительного сброса кэша повторного использования в платформе есть метод ОбновитьПовторноИспользуемыеЗначения(). Он очищает кэш всех модулей с признаком повторного использования в текущем сеансе. Типовой сценарий — вызов после записи настроек, которые участвуют в кэше: пользователь изменил константу, код вызвал ОбновитьПовторноИспользуемыеЗначения(), и следующие обращения получат свежие данные.
Учтите: метод сбрасывает кэш только текущего сеанса. Если настройку изменил один пользователь, остальные сеансы продолжат работать со старыми значениями до своего перезапуска. В многопользовательской системе это нужно учитывать при проектировании: либо принять задержку обновления, либо не кэшировать такие данные на время сеанса.
// Общий модуль с повторным использованием "На время вызова"
Функция СтавкаНДСНоменклатуры(Номенклатура) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ СтавкаНДС ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.СтавкаНДС;
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Сброс кэша после изменения настроек
ОбновитьПовторноИспользуемыеЗначения();Типичные ошибки и риски при работе с кэшем
Самая частая ошибка — кэширование данных, которые меняются внутри той же транзакции. Например, функция возвращает остаток по складу, её поместили в модуль «На время вызова», а в рамках одного серверного вызова документ сначала записал движения, а потом снова запросил остаток — и получил старое значение. Результат: некорректный контроль остатков и ошибки в учёте.
Вторая группа ошибок связана с клиент-серверной архитектурой. Модуль с повторным использованием, доступный и на клиенте, и на сервере, фактически имеет два независимых кэша. Если логика рассчитывает, что клиент «увидит» значение, закэшированное на сервере, поведение будет непредсказуемым.
Третья проблема — кэширование объектов, а не значений. Функции с повторным использованием должны возвращать простые типы или ссылки. Возврат изменяемых объектов (скажем, построенного объекта СправочникОбъект) приведёт к тому, что все вызывающие получат один и тот же экземпляр, и изменения в одном месте «протекут» в другие.
Как проверить, что кэш работает, и диагностировать проблемы
Убедиться в эффекте кэширования можно двумя способами. Первый — замер производительности в конфигураторе (Отладка → Замер производительности): после включения повторного использования количество вызовов кэшируемой функции в замере сократится, хотя обращений к ней в коде столько же. Второй — технологический журнал с отбором по событиям DBMSSQL или DBPOSTGRS: повторные запросы к кэшируемым таблицам должны исчезнуть.
Если подозреваете, что проблема вызвана устаревшим кэшем, выполните простую диагностику: перезапустите сеанс пользователя. Если поведение изменилось — с высокой вероятностью виноват кэш «На время сеанса». Если нет — ищите причину в данных или коде.
Для кэша «На время вызова» диагностика сложнее: устаревание проявляется только внутри одной операции. Признак — функция возвращает значение, которое не соответствует только что записанным данным. Лечение — убрать кэширование для этой функции или перенести чтение после окончания изменяющей операции.
Как проверить результат
Количество выполнений кэшируемой функции в замере сократилось
Функция выполняется при каждом обращении — проверьте свойство модуля и типы параметров
Данные корректны и до, и после перезапуска
После перезапуска значения меняются — кэш сеанса хранит устаревшие данные
Возвращаются свежие значения
Возвращаются значения до изменения — функцию нельзя кэшировать
Когда кэш использовать нельзя и какие есть альтернативы
Не кэшируйте: остатки и обороты регистров, данные, участвующие в контроле внутри транзакции, результаты запросов с отбором по быстро меняющимся параметрам, любые данные, чьё устаревание хотя бы на секунды недопустимо по логике учёта. Также бессмысленно кэшировать функции, вызываемые один-два раза за операцию, — выигрыша не будет, а сложность добавится.
Альтернативы кэшу, которые часто решают задачу лучше: получение всех нужных данных одним пакетным запросом до цикла; передача уже выбранных данных через параметры процедур; использование временных таблиц в менеджере временных таблиц для повторно используемых выборок внутри одного запроса. Эти приёмы не создают проблемы устаревания и проще в отладке.
Практическое правило: сначала устраните лишние обращения к базе архитектурно (запросы вне циклов, пакетные запросы), и только потом добавляйте кэш для того, что действительно неизбежно читается многократно.
Как выбрать подход
Частые вопросы
Чем отличаются режимы «На время вызова» и «На время сеанса»?
Первый хранит результат только в пределах одного серверного вызова и сбрасывается автоматически — он безопаснее. Второй хранит значение до конца сеанса пользователя, даёт больший выигрыш, но требует гарантии, что данные не устареют за это время.
Как сбросить кэш повторно используемых значений?
Вызовите встроенный метод ОбновитьПовторноИспользуемыеЗначения() — он очистит кэш всех таких модулей в текущем сеансе. На другие сеансы пользователей это не влияет: им потребуется перезайти или дождаться собственного сброса.
Почему кэшируемая функция всё равно выполняется каждый раз?
Чаще всего причина в параметрах сложных типов (таблицы значений, объекты), которые платформа не может сравнить для ключа кэша, либо свойство повторного использования не установлено у модуля. Также проверьте, что функция действительно расположена в этом модуле, а не продублирована в другом.
Можно ли кэшировать остатки товаров для ускорения проведения?
Нет, это одна из самых опасных ошибок. Остатки меняются внутри самой транзакции проведения, и кэш вернёт устаревшее значение, что приведёт к некорректному контролю. Остатки нужно читать запросом непосредственно в момент контроля, при необходимости с управляемыми блокировками.
Работает ли кэш одинаково на клиенте и на сервере?
Нет. Клиент и сервер имеют независимые экземпляры кэша. Если модуль доступен в обоих контекстах, значение, закэшированное серверным вызовом, не будет видно клиентскому коду, и наоборот. Проектируйте кэшируемые функции с учётом этого разделения.
Что делать, если после изменения настройки пользователи видят старое значение?
Это типичный признак кэша «На время сеанса». Варианты: вызывать ОбновитьПовторноИспользуемыеЗначения() после записи настройки, попросить пользователей перезайти в сеанс или перевести функцию на режим «На время вызова», если настройка меняется в рабочее время.
Что важно запомнить
Кэш объектов в 1С строится на общих модулях с повторным использованием значений: «На время вызова» — безопасный режим для многократных чтений внутри операции, «На время сеанса» — для констант и настроек. Никогда не кэшируйте остатки и данные, меняющиеся в транзакции. Проверяйте эффект замером производительности, а устаревание диагностируйте перезапуском сеанса.