ORM D7 умеет кэшировать результат выборки штатно — без обёртки в Cache API вручную. Параметр cache в getList, тегированный кэш и грамотная инвалидация снимают лишнюю нагрузку с БД на часто повторяющихся запросах.
Параметр cache в getList
Самый простой способ закэшировать выборку — передать в getList() параметр cache с временем жизни в секундах:
$rows = ProductTable::getList([
'filter' => ['=ACTIVE' => 'Y'],
'select' => ['ID', 'NAME', 'PRICE'],
'cache' => ['ttl' => 3600],
])->fetchAll();
ORM сама вычислит ключ кэша по параметрам запроса (filter, select, order и т.д.) и положит результат в файловый или иной кэш согласно настройкам сайта. При повторном вызове с теми же параметрами SQL не выполнится, а данные вернутся из хранилища кэша. Это особенно заметно на страницах со множеством одинаковых выборок справочников: первый хит прогревает кэш, остальные читают готовый результат.
Кэширование запросов со связями
По умолчанию ORM не кэширует запросы с JOIN — из соображений корректной инвалидации. Чтобы разрешить кэш для выборок со связями, добавьте флаг cache_joins:
$rows = OrderTable::getList([
'select' => ['ID', 'USER.NAME'],
'cache' => ['ttl' => 1800, 'cache_joins' => true],
])->fetchAll();
cache_joins вы берёте на себя контроль актуальности: если изменится связанная сущность, автоматической тегированной инвалидации join'а может не хватить. Ставьте разумный TTL и продумайте сброс.Для объектного синтаксиса эквивалент — методы Query::setCacheTtl() и Query::cacheJoins(true). На практике cache_joins оправдан там, где связанная таблица меняется редко (справочники статусов, типов, валют), а основная выборка тяжёлая и повторяется часто.
Объектный синтаксис Query
При работе через объект Query кэш настраивается методами-сеттерами, что удобно для динамически собираемых запросов:
use Bitrix\Main\ORM\Query\Query;
$result = ProductTable::query()
->setSelect(['ID', 'NAME'])
->setFilter(['=ACTIVE' => 'Y'])
->setCacheTtl(3600)
->cacheJoins(true)
->exec()
->fetchAll();
| Метод | Аналог в getList |
|---|---|
setCacheTtl(int) | cache => ['ttl' => N] |
cacheJoins(bool) | cache => ['cache_joins' => true] |
Тегированный кэш и сброс
Проблема любого кэша — устаревание. Битрикс использует тегированный кэш: записи помечаются тегами, и при изменении данных теги сбрасываются, инвалидируя связанные записи. Для ORM-таблиц ядро само регистрирует теги вида имя_таблицы при включённом управляемом кэше.
- включите управляемый кэш:
Настройки → Автокэширование → Управляемый кэш; - методы сущности
add()/update()/delete()сбрасывают тег своей таблицы автоматически; - ручной сброс — через
Application::getInstance()->getTaggedCache().
Пример ручной пометки и сброса тега:
$taggedCache = \Bitrix\Main\Application::getInstance()->getTaggedCache();
$taggedCache->clearByTag('my_product_table');
Инвалидация при записи
Когда вы меняете данные напрямую в БД (минуя ORM) или через внешний обмен, автоматический сброс тега не сработает — кэш отдаст устаревшие данные. В таких случаях инвалидируйте вручную:
// после массового импорта в таблицу
$cache = \Bitrix\Main\Application::getInstance()->getTaggedCache();
$cache->startTagCache('/orm');
$cache->registerTag('my_product_table');
$cache->endTagCache();
$cache->clearByTag('my_product_table');
$connection->query() не трогает ORM-события и теги. Всегда сбрасывайте кэш вручную после низкоуровневой записи, иначе получите «залипший» результат.Когда кэшировать, а когда нет
Кэш ORM — не универсальное решение. Оцените профиль запроса:
| Ситуация | Кэшировать? |
|---|---|
| Справочники, редко меняются | Да, большой TTL |
| Каталог с фильтрами (мало вариантов) | Да, с тегами |
| Персональные данные (корзина, профиль) | Нет — ключи размножатся |
| Запрос с уникальным фильтром на каждый вызов | Нет — кэш не переиспользуется |
- кэшируйте выборки с ограниченным набором вариантов параметров;
- избегайте кэша для запросов, где фильтр почти всегда уникален — вы засорите хранилище;
- для тяжёлой аналитики комбинируйте ORM-кэш с внешним хранилищем (Memcached/Redis) через настройки кэша сайта.
Итог
Штатное кэширование ORM закрывает большинство сценариев: cache/ttl для простых выборок, cache_joins для связей, тегированный кэш для автоматической инвалидации через add()/update()/delete(). Главное — помнить про ручной сброс тегов при прямой записи в БД и не кэшировать запросы с уникальными фильтрами.
Мы в B2Bsite настраиваем кэширование и инвалидацию на высоконагруженных проектах Битрикс — от справочников до каталогов на десятки тысяч SKU. Если ваш сайт упирается в БД под нагрузкой, поможем выстроить многоуровневый кэш с корректным сбросом и предсказуемой производительностью.
Частые вопросы
Как включить кэш для конкретной выборки ORM?
Передайте в getList параметр cache с ключом ttl, например 'cache' => ['ttl' => 3600]. При объектном синтаксисе используйте метод setCacheTtl(3600) у объекта Query.
Почему выборка со связью не кэшируется?
По умолчанию ORM не кэширует запросы с JOIN ради корректной инвалидации. Разрешить кэш можно флагом cache_joins => true или методом cacheJoins(true), но тогда контроль актуальности связей на вас.
Как строится ключ кэша ORM?
По нормализованным параметрам запроса — фильтру, выборке, сортировке, группировке. Разные значения параметров дают разные записи кэша, поэтому уникальные фильтры засоряют хранилище.
Инвалидируется ли кэш автоматически при изменении данных?
Да, если включён управляемый кэш: методы add(), update() и delete() сущности сбрасывают тег таблицы. Но прямая запись в БД мимо ORM теги не трогает.
Как сбросить кэш после массового импорта в БД?
Вручную через тегированный кэш: получите getTaggedCache() из Application и вызовите clearByTag() с именем тега таблицы. Иначе выборки будут отдавать устаревшие данные.
Стоит ли кэшировать персональные выборки?
Обычно нет. Персональные данные вроде корзины или профиля имеют уникальные параметры на пользователя, поэтому ключи кэша размножаются и переиспользования почти нет.
Можно ли хранить кэш ORM в Redis или Memcached?
Да, ORM использует общий механизм кэша сайта. Если в настройках кэширования выбран Memcached или Redis, результаты выборок лягут туда же, что ускоряет доступ под нагрузкой.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.