J'ai le code suivant qui perfrome une requête simple d'une seule table d'une base de données Oracle.
select ID, FIRSTNAME, LASTNAME from PERSONS where lower(FIRSTNAEM) = 'john' and rownum <= 1
4 Réponses :
Je viens de regarder le plan Changer la requête produite par Hibernate va être impossible sans modifier le code source hibernate lui-même. < / p> Note, la raison pour laquelle cette nidification est nécessaire devient évidente lorsque vous essayez d'introduire un produit Résultats différents à p> comme le EDIT: P> Pour référence Voici la sortie du plan d'explication, et c'est exactement la même chose pour les deux requêtes: p> la performance peut être amélioré en mettant un indice fonctionnel sur expliquer code> pour les requêtes similaires à la vôtre et que le plan est exactement le même pour les deux requêtes, donc je ne sais pas les raisons de performance que votre DBA suggère. < p> Envelopper la requête avec
Sélectionnez * à partir de (...) où ROWNUM = 1 code> introduit un arrêt d'arrêt qui arrête la requête interne après une ligne. Oracle sait que vous ne voulez pas réellement obtenir tous les résultats de la sous-requête, puis prendre la première rangée. P>
commander par code> Clause: p>
où rownum code> est appliqué avant la commande
par clause code> .... p >
inférieur (nom_nom) code> mais qui serait utilisé par les deux requêtes exactement la même. p> p>
bref - vous ne le faites pas. Il n'y a presque jamais suffisamment de raison pour modifier les requêtes que l'hibernation génère et j'ai des doutes Seroius qu'il est possible sans modifier le code source.
La seule simplification que je peux penser est d'appeler Vous pouvez cependant améliorer la requête un peu. p> Vous connaissez le nom simple de la classe que vous interrogez. Il n'est pas nécessaire de l'obtenir de l'entité d'abord et de concaténer, utilisez simplement P> Paramètres de concaténation pour une requête n'est pas une bonne pratique. Il rend votre requête vulnérable aux attaques d'injection SQL. Il est préférable d'écrire: p> getResultlist (). Obtenez (0) code> au lieu de
Getingleresult () code>. Cela simplifierait un peu le SQL généré, mais entraînerait une performance, pas une amélioration, car vous allez chercher toutes les lignes correspondantes de DB. P>
Sélectionnez A de la personne A ... code> p>
Je pense que appeler getResultlist () Ce sera une meilleure performance pour laisser Oracle ne renvoyer qu'une seule rangée.
@ Beny23 Oui, définitivement, cela aggravera la performance, mais cela simplifiera la requête un peu. Je l'ai rendu plus explicite dans la réponse maintenant, ce n'était pas vraiment clair.
Que se passe-t-il si GetResultList () devrait renvoyer 1 ligne en utilisant un champ unique dans la clause WHERE?
@RUEUEONEHEART - Je ne sais pas si le DB sera suffisamment intelligent pour s'arrêter après le premier match, comme il sera sur Getingleresult code>. Il sera probablement un peu moins efficace car il y a plus de travail à faire - créer la liste, etc.
Je suggère fortement que vous utilisez des paramètres de requête:
select * from (...) where rownum <= ?
Considérant p> wrapper: cela ne coûte aucune performance. Vous pouvez simplement l'ignorer. P> p>
J'ai été surpris, personne n'a suggéré de réécrire comme une requête natale au lieu de coller à quel hibernate génère. J'avais le même problème, même si le mien n'a rien à voir avec la performance, mais le résultat de la requête n'a jamais été la même chose, en infrigeant la requête était difficile à comprendre. P>
Le meilleur moyen d'aller pour des raisons à court et à long terme est de prendre le contrôle de la requête, d'utiliser une requête natale n'importe où, à tout moment possible. Écrivez simplement la requête comme votre DBA suggérait et mettez-le en tant que JPQL NamednativeQuery, et tout le monde est heureux. Profiter! P>
Tout d'abord, je créerais un index sur le champ FieldName.
@Stefanbe: Et cet indice serait ignoré lorsque la clause où utilise une fonction une fonction. Vous auriez besoin d'un indice fonctionnel ...
Ah ok. ne sais pas ça