4.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 экземпляров. Размер по умолчанию - 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
.На поведение кэша запросов оказывают влияние следующие свойства приложения:
-