Améliorer les performances d'Hibernate
Bonjour à tous,
je travaille actuellement, dans un cadre professionnel, sur un projet J2EE utilisant Hibernate pour le mapping o/r. La base de données sur laquelle je travaille contient plusieurs tables relativement similaires, contenant différents types de produits. Nous avons donc choisi de les regrouper à l'aide de la stratégie "une table par classe concrète" (http://www.hibernate.org/hib_docs/v3...bleperconcrete), laquelle est représentée par une hiérarchie de classes du côté objet.
Après quelques petits soucis, nous avons réussi à mapper le tout pour que cela fonctionne. Malheureusement, ces différentes tables contiennent plusieurs millions de lignes chacune, ce qui a tendance à très fortement dégrader les performances d'Hibernate, étant donné que les requêtes qu'ils génèrent ne sont pas des plus rapides. Je m'explique :
Voici un exemple (que j'ai volontairement simplifié et en partie renommé) de la requête SQL générée par Hibernate pour récupérer un ensemble de produits, contenus dans les différentes tables, mais rattachés à la même commande :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
select
produits0_.libelle as libelle3_,
produits0_.num_commande as num_commande41_2_,
produits0_.a_envoyer as a5_41_2_,
produits0_.clazz_ as clazz_2_
from (
select
libelle,
num_commande,
a_envoyer,
1 as clazz_
from produit_1
union select
libelle,
num_commande,
a_envoyer,
2 as clazz_
from produit_2
) produits0_
where produits0_.num_commande=? |
Etant donné le nombre de lignes contenues dans les différentes tables, cette requête prend plusieurs minutes pour s'exécuter (mon record doit tourner autour de 20 min !!). Ceci est dû au "select" central travaillant avec l'"union".
En effet, il suffit de transformer la requête comme suit pour que le même résultat soit obtenu en 0,01s :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
select
produits0_.libelle as libelle3_,
produits0_.num_commande as num_commande41_2_,
produits0_.a_envoyer as a5_41_2_,
produits0_.clazz_ as clazz_2_
from (
select
libelle,
num_commande,
a_envoyer,
1 as clazz_
from produit_1
where num_commande=?
union select
libelle,
num_commande,
a_envoyer,
2 as clazz_
from produit_2
where num_commande=?
) produits0_ |
Etant donné que je possède le code de la requête beaucoup plus rapide, j'aurai pu l'implémenter directement dans le code et trouver un moyen de convertir les résultats dans les différentes classes concernées.
Le problème est que cette requête est générée automatiquement lorsque Hibernate essaye de récupérer une collection de produits, appartenant à une commande en tant qu'attribut (nous avons activé l'option Lazy-loading pour limiter le nombre de données chargées). Nous n'y avons donc pas accès.
Connaissez-vous un moyen (en mappant différemment les tables, avec une option Hibernate à activer...) d'améliorer les performances des requêtes générées automatiquement par Hibernate ou encore de donner à Hibernate les requêtes à utiliser pour les sélectionner les attributs souhaités ?
Merci d'avance pour vos réponses,
MiniMarch