J'utilise Hibernate EntityManager et j'estime un ralentissement étrange dans mes requêtes hibernate. Jetez un coup d'œil à ce code: Ceci s'exécute dans environ 750 ms sur ma machine. Pas flamboyant rapide considérant qu'il s'agit simplement de sélectionner un entier constant, mais acceptable. Mon problème se pose au moment où toutes les entités sont chargées dans ma session d'entitémanager avant que je ne lance ma requête: p> the em.find () est rapide, mais les requêtes d'exécution 1000 ont augmenté plus que dix fois, à environ 10 secondes. Si je mettez un J'ai utilisé une requête native ici, mais le problème existe également avec les requêtes HQL. Il semble que toutes les questions prennent au moins 70 ms chaque fois qu'une entité est dans la session d'entitémanager. P> Cette baisse de performance nous fait vraiment mal à la génération de listes où les requêtes N + 1 sont nécessaires. P> i "J'ai testé la dernière bêta hibernate 3.5 et avoir exactement le même problème. Quelqu'un a-t-il vu ce problème, ou des idées sur la manière de le réparer? P> J'utilise PostgreSQL 8.3, en utilisant les transactions locales de ressources (en cours d'exécution dans Tomcat). En utilisant le pool de connexion intégré, mais en utilisant C3P0 n'a fait aucune différence. P> p> em.clear () code> après le
em.Find () code>, le problème disparaît à nouveau et l'exécution retourne à 750ms. P>
3 Réponses :
Je dois également recommander d'utiliser un profileur JVM pour regarder où se passe le temps. Il peut également ne pas nuire à l'instruction SQL de se connecter à la session hibernate pour vous assurer que vous n'exécutez pas plus de SQL que vous ne le pensez.
La chose qui vient à l'esprit ici est la "rinçage" comportement de la session hibernate. Vous définissez explicitement un mode de rinçage spécifique à la session? Si ce n'est pas le cas, vous obtenez une "auto" rinçage qui fera une certaine quantité de vérification des objets que vous avez à votre session pour déterminer s'il existe ou non des modifications de la mémoire qui doivent être "rinçues" à la base de données (à l'intérieur d'une transaction , bien sûr). P>
Je suppose que la chose la plus facile d'essayer d'abord de voir s'il a tout effet est de modifier le code de test que vous avez montré ci-dessus pour spécifier que vous souhaitez que vous souhaitiez se produire manuellement lorsque vous valez votre base de données. transaction: p> Une autre pensée que je suppose que vous pourriez demander si vous pouvez effectuer ou non vos tâches en vrac dans un EntityManager distinct, ce qui pourrait fonctionner si vous faites des mises à jour ou Inserts. P> p>
En effet, le mode flush a été réglé sur Auto dans mon code. J'ai mis en mode flush pour commettre notre code de déclaration, nous ne faisons aucune création d'entité là-bas. Cela corrige efficacement le problème de performance. Il est simplement étrange que la vérification des objets sales ait pris environ 60 ms pour une seule entité. Merci beaucoup pour votre aperçu!
OMG, merci beaucoup, Alexandre et Bryandd! Vous avez tous deux sauvé ma vie! :) J'avais exactement le même problème ici, avec une transaction contenant une boucle avec plusieurs recherches et inserts de vrac / mises à jour à l'intérieur. Après une semaine de changement d'algorithme, de googling et de profilage, ma question de performance a été résolue avec un simple: em.setflushmode (flushmodeType.comCmit); Avant cela, tout le processus a pris environ 28 minutes, 95% dépensés sur GetSultList (). Après, tout se passe bien avec à peu près 2min. Je me demande pourquoi jpa / hibernate ne cueille pas flushmodeType.Commit le flushmode par défaut pour EntityManager ...
Votre exécution d'une requête native qui ne dit rien à propos de ce qu'elle va toucher et que l'hibernation devra donc (pour la cohérence des raisons de cohérence) Flush () contre toutes les données de toutes les tables qu'elle connaît (et votre simple recherche () pourrait ont été extraite plus qu'un seul objet pour ne pas être une opération triviale). P>
Pour optimiser cela, assurez-vous d'utiliser les méthodes SQLQUERY.ADD * pour définir ce que la requête fait réellement. Dans ce cas, Query.addsynchronizedCaceSpace ("Bogustablename") devrait faire le truc sur dire hibernate que cette requête ne fait que des données scalaires d'aucune table spécifique. P>
J'avais essentiellement le même problème (question à l'intérieur d'une boucle). J'ai procédé à une vérification du profilage avec JProfiler ... L'exécution de ma méthode intéressée a passé 572 secondes et hibernez la vérification sale prend 457 secondes de cette période (environ 80%). Incroyable, n'est-ce pas? Je dois dire que j'ai eu beaucoup d'entités gérées par EntityManager. Si j'introduit EM.FLUSH () / EM.CLEAR () ou EM.SETFLUSHMODE (FLUSHMODETYTYPECOMPMIT) dans le code incriminé, le problème de performance disparaît. P>
Le résultat du profileur est disponible à http://img1.imagilive.com/0110/hibernate_dirty_checking_bad_perfomances0ce.png p>
Avez-vous profilé? Où est la plupart du temps passé? Avez-vous des méthodes d'auditeurs / intercepteurs / de rappel définies?