10
votes

Hibernate Query Cache - Pour les objets non dans le cache du 2e niveau - Risky? utile? mauvaise pratique?

liée à cette Question < / a>

Premisse:

Ce sont mes hypothèses, basées sur ma lecture, mon expérience et votre compréhension, ils peuvent avoir tort, s'ils le sont, veuillez commenter et je ' ll Modifier la question.


1 commentaires

+1 pour une question excellemment formée, formatée et recherchée.


3 Réponses :


2
votes

seuls hypothèses :

Selon ce article de Documentation hibernate:

[cache de requête] crée deux nouvelles cachees Régions: une requête mise en cache ensembles de résultats (org.hibernate.cache.tandardquerycache), l'autre tenant des horodatages de la Mises à jour les plus récentes d'interrogateur les tables (org.hibernate.cache.updatetestampstache).

Je suppose que cela signifie que chaque fois que l'horodatage de la table requérable est plus récent que le nombre de résultats - il provoquera l'approche de la DB dans le prochain appel à cette requête et que ce qui garde le cache de requête en sécurité dans certains aspect.

Mais 2 phrases plus tard dans le même paragraphe de la documentation, il est indiqué:

Le cache de requête doit toujours être utilisé En conjonction avec le deuxième niveau cache.

Encore une fois, mon hypothèse est que c'est la seule façon dont Hibernate peut être conscient des modifications apportées à la base de données qui sont effectuées hors de cette session spécifique de l'utilisateur


0 commentaires

7
votes

Un cache de requête est un type particulier de cache de 2e niveau. Ce que vous faites référence au cache de 2e niveau, je préférerais appeler "cache d'objet".

Commentaires sur vos hypothèses:

  • La cache de requête est bonne surtout avec le cache de 2e niveau (objet AKA cache).

    Un cache de requête ne contient que les résultats bruts des requêtes en tant que touches primaires, dans Hibernate Speak, ID's. Il ne tient pas les objets hydratés réels. Cela est logique que lorsque vous exécutez une requête avec JDBC, cela ne vous donne que des objets hydratés (peuplés) à la suite de votre itération sur les Resultats. La déclaration n'est pas nécessairement correcte. Si la requête est très compliquée et prend donc très longtemps à courir, en utilisant un cache de requête, vous économiserez ce temps. En utilisant un cache de requête, vous ne économiserez pas le temps nécessaire pour charger les objets de la base de données.

    • la cache de requête est risquée si la base de données a été modifiée et que cela n'a pas été reflété au cache

      Ceci est vrai, mais il n'est pas unique d'interroger le cache, il en va de même pour ce que vous avez terminé le cache de 2e niveau, mais ce qui est typiquement appelé cache d'objet.

      alors ma première hypothèse est que Hibernate d'abord des recherches dans le Cache de session, puis au 2e niveau Cache. Cette hypothèse est-elle correcte?

      Oui, lors du chargement d'objets, c'est le comportement.

      je suppose aussi que si l'objet (foo) qui n'est pas dans le cache du 2e niveau, a été changé dans la base de données, puis Cache de requête, session croisée Scoped, retournera le mauvais identificateurs, et donc le mauvais objets. Est-ce correct?

      Oui, à la fois le cache d'objet et le cache de requête seront affectés. Ceci n'est que de préoccupation si la base de données est modifiée sans aller via hibernate. Vous pouvez potentiellement atténuer l'effet de cela en définissant le délai d'attente du cache de requête.

      est-il alors sûr de dire que l'utilisation de cache de requête pour les requêtes qui incluent informations immuables même pour non 2L Objets mis en cache, est une bonne pratique? (par ex. une question que sa clause où contient une condition qui sera toujours renvoyer les mêmes résultats, par exemple "sélectionner p.ser_num où p.id =? "Quand ser_num et les couples ID ne changent pas une fois créé)

      Pour ce type d'objets, il n'y a aucune raison de ne pas utiliser à la fois un cache d'objet et un cache de requête.

      et oui, la mise en cache de requête ne fonctionne pas au niveau de la session AKA Niveau 1 Cache. Ainsi, la raison pour laquelle lorsque vous exécutez la requête à nouveau, il frappe à nouveau la base de données. Il ne mettra pas le résultat (ID SET) d'une requête dans le cache de session.


2 commentaires

Merci pour la réponse très approfondie, une chose que je ne comprends pas. Lorsque vous avez écrit ", il ne mettra pas le résultat (jeu d'identité) d'une requête dans le cache de session." - Quand il "frappe la base de données à nouveau", exécute-t-il la requête telle quelle? Ou charte simplement les objets par ID dans une requête "Sélectionner dans"? Lorsque la portée de la session est terminée, le cache de requête doit toujours tenir les ID, même s'ils sont d'un objet non dans le cache du 2e niveau, non?


Si la requête n'est pas une requête mise en cache, elle frappera la base de données à chaque fois (la requête complète), comme vous l'avez vu. S'il est configuré pour mettre en cache, il frappera la base de données la première fois et non. Ce que je vous suggère de faire est d'activer la journalisation SQL par le paramètre hibernate ou par définition org.hibernate.sql vers le débogage afin que vous puissiez voir exactement quand il frappe la base de données.



1
votes

Pour votre question n ° 3, je ne pense pas que vous souhaitiez utiliser le cache de requête lorsque les objets ne sont pas mis en cache. Vous vous retrouverez avec tous les identifiants principaux, mais il devra frapper la base de données une fois par clé pour récupérer les objets pouvant être plus lents que d'exécuter la requête sans cache du tout. À partir de 3,3 de toute façon, peut-être dans les versions plus récentes, il attrape les objets manquants en utilisant moins de requêtes, par exemple. où id in (: ID1,: id2, ...).


0 commentaires