5.4.6. Кэши сущностей и запросов
- Кэш сущностей (Entity Cache)
-
Кэш сущностей предоставляется ORM фреймворком EclipseLink. Он хранит в памяти недавно прочитанные или записанные экземпляры сущностей, тем самым сокращая доступ к базе данных и увеличивая производительность.
Кэш сущностей используется только при извлечении сущностей по идентификатору, поэтому запросы по другим атрибутам по-прежнему выполняются на базе данных. Тем не менее, эти запросы могут стать проще и быстрее, если связанные сущности находятся в кэше. Например, если вы запрашиваете Заказы вместе со связанными Заказчиками, и не используете кэш, то SQL-запрос будет содержать JOIN с таблицей заказчиков. Если же сущность Заказчик закэширована, SQL-запрос будет только по таблице заказов, а связанные заказчики будут извлечены из кэша.
Для того, чтобы включить кэш сущностей, установите следующие свойства приложения в файле app.properties модуля core вашего проекта:
-
eclipselink.cache.shared.sales$Customer = true
- включает кэширование сущностиsales$Customer
. -
eclipselink.cache.size.sales$Customer = 500
- устанавливает размер кэша для сущностиsales$Customer
в 500 экземпляров.TipЕсли кэширование включено, всегда рекомендуется увеличить размер кэша (по умолчанию - 100). В противном случае, если запрос вернёт более 100 записей, то каждая запись будет извлечена отдельной операцией.
Факт кэширования сущности влияет на то, какой fetch mode выбирается платформой при загрузке графов сущностей. Если некоторый ссылочный атрибут представляет собой кэшируемую сущность, то fetch mode всегда будет
UNDEFINED
, что позволяет ORM извлекать ссылку из кэша вместо добавления в запрос JOIN или выполнения отдельного batch-запроса.Платформа обеспечивает координацию кэша сущностей в кластере middleware. Когда кэшированный экземпляр сущности обновляется или удаляется на одном узле кластера, тот же экземпляр на других узлах (если он загружен) будет инвалидирован, что приведет к загрузке свежего состояния из БД при следующей операции с данным экземпляром.
-
- Кэш запросов (Query Cache)
-
Кэш запросов сохраняет идентификаторы экземпляров сущностей, возвращаемых JPQL-запросами, тем самым естественно дополняя кэш сущностей.
Например, если для сущности
sales$Customer
разрешен entity cache, и запросselect c from sales$Customer c where c.grade = :grade
выполняется первый раз, происходит следующее:-
ORM выполняет запрос в базе данных.
-
Загруженные экземпляры сущности
Customer
помещаются в entity cache. -
В кэш запросов помещается соответствие между текстом запроса вместе с параметрами и списком идентификаторов загруженных экземпляров.
Когда этот же запрос с такими же параметрами выполняется второй раз, платформа находит запрос в кэше запросов и загружает экземпляры сущностей по идентификаторам из кэша сущностей, не обращаясь к базе данных.
Запросы по умолчанию не кэшируются. Указать, что запрос должен кэшироваться, можно на различных уровнях приложения:
-
Методом
setCacheable()
интерфейса Query при работе с EntityManager. -
Методом
setCacheable()
интерфейсаLoadContext.Query
при работе с DataManager. -
Методом
setCacheable()
интерфейсаCollectionDatasource
или в XML-атрибутеcacheable
при работе с источниками данных.
WarningКэшируемые запросы следует использовать только если для возвращаемой сущности разрешен entity cache. В противном случае при каждом запросе экземпляры сущности будут загружаться из базы данных по идентификаторам по одному.
Кэш запросов автоматически инвалидируется, когда через ORM выполняются операции создания, изменения или удаления с сущностями соответствующего типа. Инвалидация работает по всему кластеру среднего слоя.
JMX-бин
app-core.cuba:type=QueryCacheSupport
можно использовать для мониторинга состояния кэша и для удаления запросов из кэша. Например, если вы изменили некоторый экземпляр сущностиsales$Customer
напрямую в БД, необходимо удалить все закэшированные запросы по этой сущности с помощью операцииevict()
с аргументомsales$Customer
.На поведение кэша запросов оказывают влияние следующие свойства приложения:
-