CodeGym /Cours /Hibernate deep-dive /Hibernate Statistics : compteurs utiles

Hibernate Statistics : compteurs utiles

Hibernate deep-dive
Niveau 26, Leçon 1
Disponible

1. Rôle des Statistics à côté du journal SQL

Si le journal SQL est un enregistrement vidéo des caméras de surveillance, alors les Statistics Hibernate sont les compteurs à l’entrée : « combien de personnes sont entrées », « combien de fois la porte s’est ouverte », « combien de fois le gardien a couru après un café ». La vidéo donne des détails et un contexte, mais il est difficile de comparer rapidement deux exécutions d’un même scénario. Les compteurs ne racontent pas toute l’histoire, mais ils fournissent une image compacte, reproductible et comparable sans spéculation.

Le journal SQL a déjà montré la forme du problème. Maintenant, on veut comprendre l’ampleur : est-ce une seule requête lourde, une série de secondary selects, ou juste une impression que « quelque chose est trop ». C’est là que les compteurs sont utiles.

Concrètement, ça ressemble à ceci : vous exécutez le même cas de lecture (par exemple « page catalogue des produits actifs ») dans deux variantes d’implémentation. Le journal SQL vous dit quoi a été exécuté, et Statistics répond combien de fois et à quelle échelle. Et ce « combien » détecte très rapidement les problèmes classiques : N+1, les chargements inattendus de collections, la matérialisation d’un graphe trop grand, et même les cas où une « lecture » déclenche soudainement un flush.

Un point très important : Statistics ne remplace pas le journal SQL. Ce sont comme un résumé après avoir lu un roman. Si le roman est mauvais, le résumé ressemblera à « beaucoup de pages, peu de sens ». Mais si vous auditez la couche de données, le résumé est quand même nécessaire – sinon vous devrez chaque fois revoir la « vidéo ».

2. Activation des Statistics par profil

Les Statistics Hibernate ne sont pas activées « en permanence » pour une raison simple : collecter des métriques a un coût. Cela ajoute une petite surcharge à chaque requête et à de nombreuses opérations internes de l’ORM. Dans un projet d’apprentissage, c’est normal – nous apprenons justement à mesurer. Dans un service en production, on ne veut généralement pas garder les statistiques toujours activées : il est trop facile de rendre le système un peu plus lent « pour la beauté des graphiques ».

Dans Commerce Persistence Lab, nous vivons dans une discipline de profils. La manière typique et correcte est donc d’activer les statistiques avec un profil dédié stats, de sorte que par défaut l’application soit « normale » et se transforme en laboratoire pour le diagnostic.

La configuration minimale dans application-stats.yml peut ressembler à ceci :

spring:
  jpa:
    properties:
      hibernate:
        # Activation de la collecte des statistiques Hibernate (sinon tous les compteurs seront à zéro)
        generate_statistics: true

Cette configuration à elle seule active la collecte des statistiques. Ensuite, vous décidez comment les lire : manuellement via Statistics dans le code (c’est notre voie principale aujourd’hui) ou également via un logger, si vous préférez voir un résumé dans les logs. Mais le logger est capricieux : vous obtenez beaucoup de texte, alors que nous avons besoin d’un « instantané » de cinq chiffres pour un scénario.

Et oui, il est normal qu’en activant le profil stats, l’application devienne un peu plus « lourde » à chaque requête. Ce n’est pas un bug ni un « Hibernate ralentit encore », mais le prix conscient du microscope : quand on active la mesure, on ajoute toujours un petit coût de mesure.

3. Accès aux Statistics dans Spring Boot

Jusqu’à présent, nous avons beaucoup parlé de « Hibernate », mais notre code reste dans Spring Boot, et en surface c’est JPA (EntityManager, EntityManagerFactory). La question logique est donc : où, dans ce gâteau en couches, se cache l’objet qui fournit les statistiques ?

La réponse est simple : les Statistics vivent dans la SessionFactory Hibernate. Dans une application Spring Boot avec JPA, nous avons généralement un EntityManagerFactory, et on peut le « déballer » vers le niveau Hibernate via unwrap(...). C’est l’un des rares cas où nous descendons délibérément sous l’abstraction JPA – parce que nous avons besoin d’un diagnostic spécifique à Hibernate.

La façon la plus directe (dans n’importe quel endroit où l’on dispose d’un EntityManagerFactory) ressemble à ceci :

import jakarta.persistence.EntityManagerFactory;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;

// On « descend » de l’abstraction JPA vers Hibernate pour accéder aux statistiques
Statistics statistics = entityManagerFactory
        .unwrap(SessionFactory.class) // récupère la SessionFactory Hibernate
        .getStatistics();             // obtient l’objet statistiques (compteurs pour toute la SessionFactory)

Pour ne pas copier ce code dans tout le projet, il est plus pratique de le configurer une fois comme un Spring Bean et ensuite simplement injecter Statistics dans les services concernés. Ce n’est pas une « architecture obligatoire », mais une infrastructure d’apprentissage qui rend les laboratoires plus courts et plus clairs.

Exemple de configuration :

import jakarta.persistence.EntityManagerFactory;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HibernateStatsConfig {

    @Bean
    Statistics hibernateStatistics(EntityManagerFactory emf) {
        // Injecte Statistics en tant que bean pour éviter de dupliquer unwrap(...) dans le projet
        return emf.unwrap(SessionFactory.class).getStatistics();
    }
}

Désormais, n’importe où dans le projet (par exemple dans com.example.commerce.labsupport), on peut simplement accepter Statistics dans le constructeur. Oui, c’est un objet « global » pour toute la SessionFactory. Et c’est précisément pour cela que nous insisterons constamment sur le fait de mesurer un seul scénario, de réinitialiser les compteurs avant la mesure et de ne pas le faire en environnement multithread « tout le monde optimise tout en même temps ».

4. Prendre un snapshot sans se mentir

Les Statistics Hibernate ont une particularité insidieuse : elles semblent simples, donc très faciles à utiliser incorrectement. L’erreur la plus fréquente du débutant est de regarder les compteurs « tels quels » et de tirer des conclusions. C’est comme mesurer la vitesse d’une voiture sans remettre le compteur à zéro et sans savoir si vous rouliez ou si vous étiez garé moteur allumé.

Le rituel correct (oui, c’est un de ces rares cas où un rituel est utile) ressemble à ceci : vous choisissez un cas (lecture ou écriture), vous réinitialisez les compteurs, vous exécutez le scénario, vous récupérez les valeurs, puis vous les comparez avec une autre variante d’implémentation. Si vous ne faites pas de clear(), votre mesure inclura tout : les requêtes de démarrage de l’application, les logs de migration, les chargements de fond aléatoires, et même ce que vous faisiez dans un onglet voisin de l’IDE pendant que vous « vérifiant juste ».

Un « instantané » minimal pour un scénario peut ressembler à ceci :

import org.hibernate.stat.Statistics;

// Important : réinitialiser les compteurs avant la mesure d’un scénario spécifique
statistics.clear();
catalogQueryService.findActiveProducts(); // un seul use case

// Récupérer les valeurs immédiatement après l’exécution du scénario
System.out.println("queries=" + statistics.getQueryExecutionCount());      // queries=1
System.out.println("statements=" + statistics.getPrepareStatementCount()); // statements=1

Remarquez le point subtil : nous n’essayons pas de mesurer « toute l’application ». Nous mesurons « un seul use case ». Idéalement, à ce moment-là, vous devez nommer clairement le scénario avec des mots, comme un humain : « page catalogue des produits actifs », « charge détaillée d’une commande avec ses lignes », « tableau des commandes avec statut NEW ». Si vous ne pouvez pas nommer le scénario, vos chiffres seront également difficiles à interpréter.

Et un autre détail important : même un cas de lecture peut déclencher soudainement un flush (nous en avons déjà parlé dans le sujet flush et dirty checking). Aujourd’hui, nous ne regardons donc pas seulement les requêtes, mais nous gardons à l’esprit « n’y a-t-il pas eu d’écriture là où on ne l’attendait pas ».

5. Cinq compteurs clés

Statistics peuvent faire beaucoup de choses, mais justement à cause de cela, les débutants se noient rapidement dans les chiffres et commencent soit à ignorer l’outil, soit au contraire à en faire une religion (« la métrique dit 7, donc c’est mauvais »). Nous allons faire les choses en adulte : choisir un ensemble minimal qui apporte le maximum d’utilité pour le diagnostic de la couche de persistance, dans le cadre de ce cours.

Aujourd’hui, cinq compteurs nous intéressent : queryExecutionCount, prepareStatementCount, entityLoadCount, collectionFetchCount, flushCount. Ils couvrent bien les trois grandes questions du diagnostic : combien d’activité basée sur les requêtes a traversé l’ORM, combien de travail SQL est réellement parti au niveau JDBC, combien de données ont été matérialisées en objets managed, et s’il y a eu une écriture cachée (flush) dans un scénario censé être « en lecture seule ».

Pour plus de clarté, voici un tableau compact facile à garder en tête :

Métrique (Statistics) Ce qu’elle compte dans la pratique Quels symptômes détecte-t-elle le plus rapidement
getQueryExecutionCount() Nombre de requêtes passées par le mécanisme de requêtes Hibernate ; ce n’est pas un compteur SQL total universel Signal rapide d’activité de requêtes « bavardes » et de N+1 ; à lire avec le journal SQL, getPrepareStatementCount() et les compteurs de fetch
getPrepareStatementCount() Nombre de PreparedStatement JDBC préparés (approximativement : nombre de statements SQL réellement envoyés) Volume réel du travail SQL, y compris les UPDATE inattendus
getEntityLoadCount() Nombre d’instances d’entités chargées Sur-fetching et « trop d’entités extraites »
getCollectionFetchCount() Nombre de fois qu’Hibernate a chargé des collections (to-many) Collections paresseuses, SELECT secondaires, N+1 sur les collections
getFlushCount() Nombre de fois qu’un flush a eu lieu « Il y a une écriture dans un cas de lecture », flush-before-query, modifications cachées

Nous allons maintenant détailler chaque métrique séparément, mais avec une mise en garde importante : nous ne les lisons pas une par une. Un seul chiffre donne rarement un diagnostic correct. En général, le diagnostic naît de la combinaison de deux ou trois indicateurs, plus l’observation du journal SQL.

queryExecutionCount : signal rapide d’un scénario bavard

Lorsqu’un développeur active pour la première fois le journal SQL, il ressent souvent un mélange étrange d’émotions : c’est utile, mais après une minute, les yeux ont envie de se fermer et de partir en vacances. queryExecutionCount est un moyen de détecter rapidement si un scénario devient un comportement bavard de requêtes. Mais il ne faut pas le surestimer : ce n’est pas un compteur universel de toute l’activité SQL d’Hibernate.

Prenons un scénario simple de catalogue : nous voulons obtenir la liste des produits actifs. Nous faisons une seule requête JPQL – et nous attendons une seule requête en base. Alors queryExecutionCount dans le cas idéal de base sera égal à 1 (ou à peu près, si le scénario inclut d’autres requêtes de service obligatoires, mais dans le laboratoire nous essayons de supprimer le bruit).

Petit exemple de mesure :

// Mesure strictement pour un seul scénario
statistics.clear();
catalogQueryService.findActiveProducts();

// Devrait être proche de 1 dans un scénario « sain » (une seule requête racine)
System.out.println(statistics.getQueryExecutionCount()); // 1

Si vous retournez une List<Product> et que dans le code vous la parcourez et touchez à product.getDetails() ou product.getAssignments(), le scénario devient bavard. Cela sera presque certainement visible dans le journal SQL, et quantitativement, cela sera souvent mieux détecté par l’augmentation de prepareStatementCount, collectionFetchCount et d’autres compteurs de fetch. queryExecutionCount reste un signal rapide utile, mais ce seul chiffre ne suffit plus.

prepareStatementCount : combien de SQL sont réellement partis

Après la première rencontre avec queryExecutionCount, le débutant a souvent envie de vivre heureux : « Oh, j’ai tout compris, il suffit de réduire le nombre de requêtes et ça ira vite ». Et c’est là que prepareStatementCount nous ramène doucement sur terre. Parce que les requêtes, la préparation des statements et le travail SQL réel sont des choses proches mais pas identiques.

prepareStatementCount est plus proche de la réalité JDBC : combien de fois Hibernate a dû préparer des statements SQL pour exécution. Si, par exemple, dans un scénario de « lecture » vous modifiez accidentellement une entité gérée (du genre setName(trim())), Hibernate peut envoyer un UPDATE lors du flush, et prepareStatementCount augmentera. Pendant ce temps, queryExecutionCount peut rester petit, car un UPDATE n’est pas une « requête » au sens JPQL, mais c’est un vrai travail de base de données.

Petit exemple où prepareStatementCount détecte un travail caché :

// Réinitialisation avant de vérifier la « propreté » d’un cas de lecture
statistics.clear();
catalogQueryService.findAndAccidentallyMutateProductName(productId);

// Comparaison entre « requêtes » et « statements réels » : l’UPDATE peut n’apparaître que dans le second
System.out.println("queries=" + statistics.getQueryExecutionCount());      // queries=1
System.out.println("statements=" + statistics.getPrepareStatementCount()); // statements=2

Le chiffre « 2 » n’est pas important en tant qu’absolu. Ce qui compte, c’est qu’il soit plus élevé que ce que vous attendiez pour une simple lecture. C’est un signal : « regarde le journal SQL – il y a clairement autre chose que des SELECT ». Et c’est exactement ce dont nous avons besoin dans un audit : repérer rapidement une écriture inattendue.

entityLoadCount : combien d’entités ont été chargées

Il existe un piège très courant, surtout après avoir découvert JOIN FETCH. Le développeur fait « une seule requête » et se réjouit : queryExecutionCount = 1. Mais ensuite l’application est quand même lourde, et l’empreinte mémoire semble grande. Pourquoi ? Parce qu’« une seule requête » peut rapporter beaucoup de données qu’Hibernate transforme en objets d’entités gérées.

entityLoadCount indique combien d’instances d’entités ont été chargées. Ce n’est pas la « taille du result set en lignes » ni le « nombre de colonnes ». C’est bien « combien d’entités sont apparues dans le contexte de persistence en tant qu’objets gérés ». Pour le diagnostic, c’est extrêmement pratique : vous pouvez voir qu’un cas de lecture extrait « tout un univers d’entités » alors que métier vous n’aviez besoin que d’une liste de 20 lignes avec quatre colonnes.

Petit exemple de comparaison de deux approches sur un même scénario (conceptuellement) :

// Dans ce scénario, nous nous intéressons au volume d’entités matérialisées
statistics.clear();
catalogQueryService.findCatalogPageWithEntities();

// Si le nombre est grand, c’est un signal direct de sur-fetching, même si la requête est formellement unique
System.out.println("entities=" + statistics.getEntityLoadCount()); // entities=240

Si vous voyez que pour une « simple page de catalogue » 240 entités ont été chargées, c’est une raison de réfléchir : vouliez-vous vraiment matérialiser autant d’objets ? Ou ce scénario aurait-il dû être basé sur une projection et « léger » ? Nous ne débattons pas à nouveau de « entité vs projection » (cela a été fait plus tôt), mais les statistiques aident à voir le coût de la décision en chiffres.

collectionFetchCount : chargements supplémentaires de collections

Avec le lazy-loading sur les associations to-many, il y a un effet sournois : vous pouvez honnêtement faire une seule requête racine, obtenir une liste de commandes, puis « en cours de route » appeler order.getItems().size() ou parcourir les items dans une boucle. Pour le code Java, cela semble anodin, mais pour Hibernate, c’est un signal « initialise la collection », donc exécute des requêtes supplémentaires.

collectionFetchCount indique combien de fois ces collections ont été chargées. En pratique, c’est une métrique en or : si vous lisez une liste de commandes et que vous voyez collectionFetchCount > 0, alors quelque part vous avez touché une collection to-many de manière paresseuse, et cela mène presque à coup sûr soit à du N+1, soit à une série de SELECT secondaires.

Imaginons un scénario de liste de commandes :

// Vérifions si les collections to-many paresseuses « tirent » lors du parcours du résultat
statistics.clear();
orderQueryService.findRecentOrdersAndTouchItems();

// Toute valeur > 0 est une raison de chercher des SELECT secondaires dans le journal SQL
System.out.println("collections=" + statistics.getCollectionFetchCount()); // collections=30

Le nombre « 30 » dans le commentaire est juste une illustration : il est généralement à peu près égal au nombre de commandes dans la liste, car chaque commande charge sa collection séparément. Ensuite, vous allez dans le journal SQL et voyez un select ... from order_item where order_id=? répété plusieurs fois. Les statistiques agissent ici comme un « détecteur de fumée » : elles n’expliquent pas l’incendie en détail, mais disent « il y a de la fumée, va voir d’où ça vient ».

flushCount : signal d’alarme pour un cas de lecture

Flush est un sujet qui a déjà gâché l’humeur de beaucoup de gens, car il peut survenir « plus tôt que prévu ». Mais dans le diagnostic, flushCount est un indicateur très reconnaissant. Surtout lorsque nous mesurons un cas de lecture.

Si vous analysez un scénario de lecture, votre flushCount idéal est généralement égal à 0. Il peut devenir supérieur à zéro si vous avez modifié quelque chose dans la transaction (même accidentellement), ou si Hibernate a été contraint de synchroniser le contexte pour garantir la cohérence de la requête. Dans tous les cas, c’est un signal : « attention, le scénario n’est pas purement en lecture ».

Petit exemple :

// Cas de lecture : normalement, il ne devrait pas y avoir de synchronisation (flush) avec la base
statistics.clear();
orderQueryService.findOrdersReadCase();

// Idéal : 0. Si > 0, cherchez un accidental update / flush-before-query
System.out.println("flushes=" + statistics.getFlushCount()); // flushes=0

Si soudain flushes=1, pas de panique, ne « réparez pas Hibernate ». Ouvrez calmement le journal SQL et comprenez ce qui a causé le flush. C’est souvent un accidental update banal dû à « j’ai un peu modifié une ligne », « j’ai mis une valeur par défaut », « j’ai touché un embeddable » ou « un listener a été déclenché ». Nous n’approfondissons pas les callbacks aujourd’hui, mais un signal de flush dans un cas de lecture est toujours une raison de vérifier si la frontière entre lecture et écriture n’a pas été franchie.

6. Combinaisons de métriques : motifs de diagnostic

Après avoir examiné les cinq compteurs, une question logique se pose : « OK, qu’est-ce qui est considéré comme “bien” et “mal” ? ». La réponse n’est pas universelle, mais il existe des motifs simples qui, en développement réel, aident à comprendre en une minute dans quelle direction creuser. C’est un peu comme la médecine de base « température et tension » : ils ne posent pas de diagnostic, mais aident beaucoup à choisir la prochaine étape.

Voici quelques combinaisons typiques sous forme de tableau (un indice, pas une loi de la nature) :

Ce que vous voyez dans les métriques Ce que cela signifie souvent Que faire ensuite (dans le cadre du diagnostic)
queryExecutionCount et/ou prepareStatementCount nettement plus élevés que prévu, collectionFetchCount significatif N+1 ou SELECT secondaires dus à des to-many Ouvrir le journal SQL et chercher une requête répétée avec order_id / product_id
queryExecutionCount petit mais entityLoadCount énorme Une seule requête ramène trop d’entités (sur-fetching) Regarder pourquoi le cas de lecture lit un graphe d’entités au lieu d’un modèle de lecture léger
flushCount > 0 dans un cas de lecture Le scénario de lecture contient une écriture/modification ou un flush-before-query Chercher un accidental update, des UPDATE inattendus dans le SQL, des modifications secondaires
prepareStatementCount plus élevé que prévu Le scénario contient du « SQL en trop » (pas seulement des SELECT), ou des opérations de service supplémentaires Comparer avec le journal SQL : quels statements se sont ajoutés

Notez que ce tableau ne nous pousse pas automatiquement vers EXPLAIN. Si les compteurs montrent un comportement ORM bavard – beaucoup de requêtes, des chargements de collections, des chargements d’entités superflus – on traite d’abord le problème au niveau de la forme de lecture. C’est seulement quand il y a peu de requêtes mais que la lourdeur réside dans une seule requête SQL qu’il faut se tourner vers le SQL généré, EXPLAIN et le plan PostgreSQL.

Important : nous ne transformons pas cela en « liste de contrôle d’optimisation ». Ce sont bien des « motifs de diagnostic ». Le but de la journée n’est pas d’accélérer à tout prix immédiatement, mais de savoir dire : « le problème ressemble à du N+1 » ou « le problème ressemble à du sur-fetching », puis d’ouvrir le SQL de manière ciblée pour confirmer l’hypothèse.

Pour ancrer l’idée de « comparaison de deux variantes », on peut imaginer mentalement cette expérience : une implémentation du catalogue retourne des entités, l’autre une projection. Nous n’écrivons pas ici un code énorme, mais nous prenons deux instantanés l’un après l’autre :

// Comparaison de deux variantes d’implémentation « à compteurs propres »
statistics.clear();
catalogQueryService.findCatalogPageWithEntities();
long entitiesQueries = statistics.getQueryExecutionCount();

statistics.clear();
catalogQueryService.findCatalogPageWithProjection();
long projectionQueries = statistics.getQueryExecutionCount();

// On affiche un seul indicateur pour voir rapidement la différence de comportement ORM
System.out.println("entitiesQueries=" + entitiesQueries);     // entitiesQueries=18
System.out.println("projectionQueries=" + projectionQueries); // projectionQueries=2

Ce n’est pas une « preuve de performance ». C’est une preuve de la forme de comportement de l’ORM : dans la première variante, il y a nettement plus de requêtes. Ensuite, vous ouvrez la trace SQL et regardez pourquoi il y en a autant (souvent, ce sera le même SELECT secondaire répété).

7. Mini-infrastructure pour un snapshot

Lorsque vous faites le dixième relevé de la journée, imprimer cinq chiffres individuellement devient fastidieux. Pour cela, un petit instantané local des compteurs suffit. Pas un nouveau « cadre de projet », mais simplement un emballage compact d’une seule mesure après un scénario spécifique.

Par exemple, juste à côté de l’expérience, vous pouvez garder un tel record :

// Instantané local des compteurs pour une mesure spécifique
public record StatisticsSlice(
        long queryCount,
        long prepareStatementCount,
        long entityLoadCount,
        long collectionFetchCount,
        long flushCount
) {
}

C’est suffisant pour, après le scénario, récupérer les valeurs et les afficher sur une seule ligne :

statistics.clear();
catalogQueryService.findActiveProducts();

StatisticsSlice slice = new StatisticsSlice(
        statistics.getQueryExecutionCount(),
        statistics.getPrepareStatementCount(),
        statistics.getEntityLoadCount(),
        statistics.getCollectionFetchCount(),
        statistics.getFlushCount()
);

System.out.println(slice); // StatisticsSlice[queryCount=1, prepareStatementCount=1, entityLoadCount=20, collectionFetchCount=0, flushCount=0]

La seule règle de sécurité importante à énoncer à voix haute : statistics.clear() réinitialise les compteurs globalement pour toute la SessionFactory. Par conséquent, dans une application multithread réelle, on ne peut pas faire cela « comme ça » – vous effaceriez les chiffres d’autres scénarios. Mais dans notre laboratoire, nous mesurons localement, de manière isolée, et c’est pourquoi cette astuce est appropriée.

8. Erreurs typiques avec Hibernate Statistics

Erreur n°1 : les statistiques sont désactivées et vous mesurez du « vide ».
Le scénario le plus frustrant ressemble à ceci : vous avez écrit un beau code de mesure, appelé getQueryExecutionCount(), et il renvoie obstinément zéro. La raison est généralement simple – hibernate.generate_statistics n’est pas activé (ou le profil stats n’est pas actif). À ce moment, on a envie d’accuser Hibernate de manque de cœur, mais il n’y est pour rien : compteur éteint – compteur ne compte pas.

Erreur n°2 : oubli du statistics.clear(), vous obtenez « les chiffres de toute une vie ».
Si vous ne réinitialisez pas les compteurs avant chaque mesure, vous obtenez les statistiques non pas du scénario, mais de tout ce qui s’est passé depuis le démarrage de l’application. Cela inclut les migrations, les seed data, vos requêtes aléatoires, et même ce qu’a fait le test voisin. De tels chiffres ne peuvent pas être honnêtement comparés entre eux, car vous comparez deux « contextes de vie » différents.

Erreur n°3 : vous avez mesuré non pas un seul use case, mais « à peu près quelque chose ».
Statistics ne sont utiles que lorsque vous pouvez dire : « voici la méthode / le scénario spécifique que je mesure actuellement ». Si à l’intérieur de la mesure vous appelez plusieurs services, faites ensuite une autre requête « au cas où », loggez des entités et initialisez accidentellement des collections, le snapshot devient une bouillie. Essayez de mesurer un seul scénario sous sa forme la plus pure.

Erreur n°4 : croire un seul chiffre et ignorer les autres.
Parfois, un développeur voit queryExecutionCount=1 et fête la victoire, alors que entityLoadCount a décollé dans l’espace. Ou l’inverse : on est fier d’avoir réduit entityLoadCount, mais on a accidentellement augmenté collectionFetchCount. Le diagnostic ORM est presque toujours multidimensionnel : il faut regarder l’ensemble des métriques, pas une seule.

Erreur n°5 : comparer deux exécutions dans des conditions et sur des données différentes.
Si dans la première mesure vous avez 20 produits, et dans la seconde 2000 produits (parce que vous avez activé big-dataset), alors les différences dans les compteurs ne seront pas uniquement dues à votre code. Ce sont tout simplement des scénarios différents. Pour comparer, fixez les paramètres d’entrée : taille de page, filtre, statut, et si possible, le même ensemble de données.

1
Mission
Hibernate deep-dive, niveau 26, leçon 1
Bloqué
Snapshot minimal de Hibernate Statistics
Snapshot minimal de Hibernate Statistics
1
Mission
Hibernate deep-dive, niveau 26, leçon 1
Bloqué
Comparaison du chargement d'entités et de la projection constructeur selon les compteurs
Comparaison du chargement d'entités et de la projection constructeur selon les compteurs
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION