Hibernate Pagination à l'aide de requêtes HQL
Hibernate Pagination Question
J'ai un problème qui est lié à l'Hibernation de la Pagination et pour une certaine mesure, cela a été expliqué dans
Mysql Optimisation De La Pagination
L'utilisation d'Hibernate est ScrollableResults à lire lentement de 90 millions de disques
Des problèmes avec la Pagination et le Tri
Détails
Requête HQL de l'Application:
Query q = session.createQuery("from RequestDao r order by r.id desc");
q.setFirstResult(0);
q.setMaxResults(50);
Requête renvoie 3 millions de documents et pour la pagination nous en sommes à seulement 50 de ces enregistrements, la pagination de la page est très lent, car à chaque actualisation, nous appelons la requête qui bénéficient de 3 millions de dossiers et de ceux que nous avons seulement mis 50 enregistrements.
Ma principale question est
Ne HQL va toujours et les coups de base de données ou faut-il aller frapper la session ou de la mémoire pour chercher les données et si ça se passe à chaque fois à frapper la base de données et obtenir jeu de résultats, alors il est très bon du point de vue des performances, ce qui serait la meilleure des solutions pour l'améliorer?
À l'aide de requêtes HQL en veille prolongée est-il un moyen que nous pouvons requête de base de données et obtenir seulement 50 enregistrements d'abord et ensuite obtenir d'autres documents requis par l'utilisateur. Ce défi est vraiment entraînant vers le bas de l'application, de sorte que ce serait la meilleure façon de résoudre ce problème?
Requête HQL générés dans les journaux
from com.delta.dao.RequestDao r order by r.id desc
Hibernate Requête Générée
select
getrequest0_.ID as ID24_,
getrequest0_.TIME as START3_24_,
getrequest0_.STAT as STATUS24_,
getrequest0_.SUM as SUMMARY24_,
getrequest0_.OUTNAME as OUTPUT7_24_,
getrequest0_.INPNAME as INPUT8_24_,
getrequest0_.REQUEST_DATE as requestT9_24_,
getrequest0_.PARENT_ID as PARENT10_24_,
getrequest0_.INTER_TYPE as INTERPO60_24_,
getrequest0_.OPEN_INT as OPEN61_24_,
getrequest0_.SOURCE_TYPE as SOURCE62_24_,
getrequest0_.TARGET_TYPE as TARGET20_24_,
getrequest0_.SOURCE as SOURCE14_24_,
getrequest0_.COPY_DATA as COPY16_24_,
getrequest0_.CURVE as GENERATE63_24_,
getrequest0_.TITLE as TITLE24_,
getrequest0_.TIME_ID as TIMESERIES12_24_,
getrequest0_.TASK_NAME as TASK51_24_
from
REQUEST getrequest0_
where
getrequest0_.KIND='csv'
order by
getrequest0_.ID desc
Ici est la Expliquer le Plan de pour la requête:
| id | select_type | table | type | possible_keys | clé | key_len | ref | lignes | filtrée | Extra | | 1 | SIMPLE | getrequest0_ | ref | TR_KIND_ID | TR_KIND_ID | 6 | const| 1703018 | 100.00 | à l'Aide de lequel |
Informations supplémentaires: l'exécution de la Requête avec et sans clause order by sur 50 limite d'enregistrements
Si je exécuter la requête with order
clause de requête prend 0.0012 s avec réglage LIMIT 50
et without order
clause, même requête prend 0.0032 s avec le même LIMIT 50
.
Également comment pouvons-nous trouver si:
- Particulier Requête HQL est de frapper la base de données et pas de cache ou d'obtenir des informations de session?
- Est-il vrai que la Requête HQL toujours frappé base de données pour obtenir le résultat et les Critères aller frapper la session ou de cache et d'obtenir des résultats?
- Aussi dans mon mentionnées ci-dessous requête:
a) Query q = session.createQuery("from RequestDao r order by r.id desc"); b) q.setFirstResult(0); c) q.setMaxResults(50);
à un, est-il vrai que nous obtenons le résultat à partir de la base de données et de les stocker dans la mémoire ou si pas et en ce moment nous avons 3 millions de résultats dans le jeu de résultats, puis en b et c et nous avons fixé la valeur de décalage et limite donc sur la page, on peut seulement voir 50 résultats jusqu'à maintenant, où sont les 3 autres millions de disques et sur notre deuxième appel à cette requête, nous ne serons pas aller frapper base de données et d'obtenir 3 millions d'enregistrements et de les mettre en mémoire, puis à c de nouveau nous avons mis 50 enregistrements et aller sur une sur.
Cette question n'est pas claire pour moi, et qui seraient donc très reconnaissant si quelqu'un peut fournir d'explication claire et détaillée que la façon dont cela fonctionne, et ce qui serait la meilleure solution pour ce problème.
Mise à jour
Comme il s'avère, la question éprouve n'est pas lié à l'affichage des dossiers sur la page mais j'ai un filtre sur cette page et sur chaque requête ai toutes déroulant valeurs à nouveau à partir de la base de données et il y a certaines choses funky se passe là-bas qui est à l'origine de montée temps de chargement de page.
Je suis en train de multiples imbriquées hibernate requêtes de base de données et l'obtention de résultats, ce qui serait une solution optimale pour ce problème?
J'ai juste édité ma réponse afin de refléter la mise à jour.
OriginalL'auteur Rachel | 2012-01-25
Vous devez vous connecter pour publier un commentaire.
Votre requête indique la base de données pour trier tous les enregistrements qui satisfont la clause where. Il peut trier des millions d'enregistrements avant de rentrer, vous top 50.
MODIFIER 1/26: Maintenant que les questions spécifiques qui ont été clarifiés, je vais essayer de répondre plus précisément.
Chaque fois que vous exécutez la requête comme ça, Hibernate va à la base de données. Même plus, qu'il chasse tous les nouveaux/mise à jour des données dans la session sur le disque. Si tel est votre cas, ce comportement peut contribuer à la lenteur.
De l'utilisation d'Hibernate Query API effectue en général assez bien dans la plupart des situations et est compatible avec une large variété de plateformes de base de données. Si vous êtes vraiment préoccupé par la serrant à la dernière goutte de la performance de votre couche d'accès aux données, vous pouvez écrire votre propre natif de requête SQL pour sélectionner les 50 meilleurs résultats. Mais dès que vous faites cela, vous aurez presque certainement en vrac de la base de données de l'indépendance. Donc, d'évaluer vos coûts par rapport aux avantages.
Votre requête fois semble être la seule millisecondes gamme. C'est généralement aussi bon qu'il obtient avec les bases de données relationnelles qui stockent des données sur le disque. De sorte que vous pouvez évaluer si vous avez en effet un problème de performance.
MODIFIER 1/27: OK. Il semble que le problème dans la conception globale de la page. J'avais été en utilisant AJAX pour les 7 dernières années, donc je n'ai pas l'habitude d'avoir à attendre pour le filtrage des contrôles d'INTERFACE utilisateur pour redessiner lorsque vous allez à travers les pages d'un tableau. Je suppose que, commutation de l'INTERFACE utilisateur de l'application des cadres n'est pas une option dans votre cas. Vous devez comprendre comment optimiser le chargement des données pour les listes déroulantes et autres. Ces données changent fréquemment? Pouvez vous cache quelque part dans la demande? Si vous avez à les charger à chaque fois, pouvez-vous sortir avec seulement obtenir l'affichage des chaînes au lieu de l'ensemble des objets?
quelles seraient les autres de façon à optimiser la requête pour s'assurer que la performance est améliorée?
aussi, quand nous disons
before returning you top 50
, après la requête récupère le résultat de la base de données, est-il conserver ces 3 millions d'enregistrements dans la mémoire et ne le tri dans la mémoire ou exactement où sont les données?Le tri est effectué sur le serveur de base de données. Serveur de base de données utilise à la fois la mémoire et d'espace disque dur. Un indice sur DEMANDE.ID devrait vraiment accélérer les choses.
Nous avons déjà index sur demande.id et donc je ne vois pas si c'est la question.
OriginalL'auteur Olaf
Si vous définissez le premier résultat et le nombre maximum de résultats Hibernate n'récupérer ces entrées de la base de données. Si c'est lent, jeu de résultats maximum à 1 et activer la journalisation SQL pour voir quelles associations sont chargés.
Hibernate supporte également plusieurs caches:
* le premier niveau du cache: uniquement être utilisé durant une session Hibernate qui correspond souvent à une transaction
* cache de second niveau: utilisé au cours de la séance/les limites de transaction, mais surtout par une recherche par id méthodes
* cache de requêtes: si activé Hibernate de recherche les résultats de la requête à partir de là en premier. Toutefois, la requête doit être le même en termes de HQL et les paramètres de sorte que chaque page peut être chargé à partir de la DB une fois et ensuite être mis en cache. (Pour plus d'informations, jetez un oeil ici: http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-querycache)
Veuillez noter que la mise en cache nécessite la mémoire du tas et selon la taille de votre entités de mise en cache de 3 millions d'entités pourraient entraîner une mémoire énorme hit, donc un renforcement de la collecte des ordures qui frapperait performance.
si c'est exact que hibernate est seulement de mieux en 50 premiers résultats à partir de la base de données mais je me demande pourquoi ma demande est prise en enfer beaucoup de temps, j'ai essayé de journalisation sql et c'est le hibernate, sql généré, pas sûr de ce que devraient être les prochaines étapes pour résoudre ce mystère.
avez-vous essayer d'exécuter la requête SQL générée par Hibernate? Est-ce long? Si oui, avez-vous un indice
REQUEST.KIND
et peut-être surREQUEST.ID
trop?J'ai essayé cette requête est de prendre environ
1 min
mais quand je suis en cours d'exécution de cette requête à partir de la ligne de commande puis il prendre le temps pour le résultat à obtenir sauté hors.J'ai index sur
KIND + ID
OriginalL'auteur Thomas