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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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