java - example - ¿Cuándo y cómo usar la memoria caché de segundo nivel de hibernación?
hibernate cache second level (3)
Tengo problemas para entender cuándo hibernación golpea la memoria caché de segundo nivel y cuándo invalida la memoria caché.
Esto es lo que entiendo actualmente:
- El caché de segundo nivel almacena entidades entre sesiones, el alcance es el SessionFactory
- Tienes que decir qué entidades almacenar en caché, ninguna entidad se almacenará en caché de forma predeterminada
- El caché de consultas almacena los resultados de las consultas en el caché.
Lo que no entiendo es
- ¿Cuándo hibernate golpea este caché?
- Digamos que configuré la caché de segundo nivel pero no el caché de consultas. Quiero almacenar en caché a mis clientes, hay 50000 de ellos. ¿De qué manera puedo recuperar a los clientes del caché?
- Supongo que puedo obtenerlos por id del caché. Eso sería fácil pero tampoco es digno de almacenamiento en caché. Pero, ¿y si quiero hacer algunos cálculos con todos mis clientes? Digamos que quiero mostrar una lista de los clientes, ¿cómo podría acceder a ellos?
- ¿Cómo obtendría todos mis clientes si el almacenamiento en caché de consultas está desactivado?
- ¿Qué pasaría si alguien actualizó a uno de los clientes?
- ¿Se invalidaría ese cliente en el caché o se invalidaría a todos los clientes?
¿O estoy pensando en el almacenamiento en caché totalmente equivocado? ¿Cuáles serían los usos más apropiados de la memoria caché de segundo nivel en ese caso? La documentación de hibernación no está nada clara sobre cómo funciona la memoria caché en realidad. Solo hay instrucciones sobre cómo configurarlo.
Actualización: Así que he llegado a comprender que el caché de segundo nivel (sin caché de consultas) sería bueno para cargar datos por id. Por ejemplo, tengo un objeto de usuario que quiero verificar para los permisos en cada solicitud en una aplicación web. ¿Sería este un buen caso para reducir el acceso a la base de datos almacenando en caché al usuario en el segundo nivel de caché? Me gustaría almacenar el ID de usuario en la sesión o en cualquier otro lugar y cuando necesite verificar los permisos, cargaría al usuario por su id y verificaría los permisos.
Antes que nada, hablemos de la caché de nivel de proceso (o de la memoria caché de segundo nivel como lo llaman en Hibernate). Para que funcione, deberías
- configurar el proveedor de caché
- diga hibernar qué entidades almacenar en caché (a la derecha en el archivo hbm.xml si usa este tipo de mapeo).
Le dice al proveedor de memoria caché cuántos objetos debe almacenar y cuándo / por qué deberían invalidarse. Entonces digamos que tiene una entidad de Libro y una de Autor, cada vez que la obtiene de la base de datos, solo aquellas que no están en la caché se seleccionarán de la base de datos actual. Esto aumenta el rendimiento significativamente. Es útil cuando:
- Escribe en la base de datos solo a través de Hibernate (porque necesita una forma de saber cuándo cambiar o invalidar entidades en la memoria caché)
- Lees objetos a menudo
- Usted tiene un solo nodo y no tiene replicación. De lo contrario, tendrá que replicar la caché (usar cachés distribuidos como JGroups), que agrega más complejidad, y no se escala tan bien como compartir aplicaciones.
Entonces, ¿cuándo funciona el caché?
- Cuando
session.get()
osession.load()
el objeto que se seleccionó previamente y reside en el caché. La memoria caché es un almacenamiento donde ID es la clave y las propiedades son los valores. Entonces, solo cuando existe la posibilidad de buscar por ID, puede eliminar el golpear el DB. - Cuando tus asociaciones son cargadas perezosas (o cargadas ansiosas con selects en vez de uniones)
Pero no funciona cuando:
- Si no selecciona por ID. Nuevamente: el segundo nivel de caché almacena un mapa de las identidades de las entidades a otras propiedades (en realidad no almacena objetos, sino los datos), así que si su búsqueda se ve así:
from Authors where name = :name
, entonces no lo hace t toca el caché. - Cuando usa HQL (incluso si usa
where id = ?
). - Si en su mapeo usted establece
fetch="join"
, esto significa que para cargar asociaciones, las uniones se usarán en todas partes en lugar de declaraciones select separadas. La memoria caché de nivel de proceso funciona en objetosfetch="select"
solo si se usafetch="select"
. - Incluso si tiene
fetch="select"
pero luego en HQL usa join para seleccionar asociaciones, esas uniones se emitirán de inmediato y sobrescribirán todo lo que especificó en hbm.xml o anotaciones.
Ahora, sobre Query Cache. Debe tener en cuenta que no es un caché separado, es un agregado al caché de nivel de proceso. Digamos que tienes una entidad de país. Es estático, por lo que sabe que cada vez habrá el mismo conjunto de resultados cuando diga from Country
. Este es un candidato perfecto para el caché de consultas, almacenará una lista de identificadores en sí mismo y la próxima vez que seleccione todos los países, devolverá esta lista al caché de nivel de proceso y este último, a su vez, devolverá objetos para cada ID ya que estos objetos ya están almacenados en la memoria caché de segundo nivel. La caché de consultas se invalida cada vez que cambia algo relacionado con la entidad. Digamos que configuró from Authors
para ubicarlos en una Caché de consultas. No será efectivo ya que el autor cambia a menudo. Por lo tanto, debe usar Query Cache solo para datos más o menos estáticos.
Tarde en la fiesta, pero quería responder sistemáticamente a esta pregunta que muchos desarrolladores preguntan.
Tomar su pregunta una por una aquí es mi respuesta.
Q. ¿Cuándo hibernate golpea este caché?
A. La memoria caché de primer nivel está asociada con el objeto Session . La memoria caché de segundo nivel está asociada con el objeto Session Factory . Si el objeto no se encuentra en el primero, entonces se verifica el segundo nivel.
P. Digamos que he configurado el caché de segundo nivel pero no el caché de consultas. Quiero almacenar en caché a mis clientes, hay 50000 de ellos. ¿De qué manera puedo recuperar a los clientes del caché?
A. Recibiste esa respuesta en tu actualización. Además, el caché de consultas almacena solo la lista de ID del objeto y los objetos que almacenan sus ID en el mismo caché de segundo nivel. Entonces, si activa el caché de consultas, utilizará el mismo recurso. Neat verdad?
P. Supongo que puedo obtenerlos por id desde el caché. Eso sería fácil pero tampoco es digno de almacenamiento en caché. Pero, ¿y si quiero hacer algunos cálculos con todos mis clientes? Digamos que quiero mostrar una lista de los clientes, ¿cómo podría acceder a ellos?
A. Contestado arriba.
P. ¿Cómo obtendría todos mis clientes si el caché de consultas está desactivado?
A. Contestado arriba.
P. ¿Qué pasaría si alguien actualizara a uno de los clientes? ¿Se invalidaría ese cliente en el caché o se invalidaría a todos los clientes?
R. Hibernate no tiene ni idea, pero podría utilizar otras cachés distribuidas / IMDG de terceros para implementarlas como hibernación de caché de segundo nivel y hacer que se invaliden. por ejemplo, TayzGrid es uno de esos productos y hay más, supongo.
- el caché de segundo nivel es un almacén de clave-valor. Solo funciona si obtiene sus entidades por ID
- la memoria caché de segundo nivel se invalida / actualiza por entidad cuando una entidad se actualiza / elimina mediante hibernación. No se invalida si la base de datos se actualiza de una manera diferente.
- para consultas (p. ej., lista de clientes) use el caché de consultas.
En realidad, es útil contar con un caché distribuido de clave-valor: eso es lo que es memcached, y potencia Facebook, Twitter y muchos más. Pero si no tienes búsquedas por ID, entonces no será muy útil.