Peuvent Hiberner être utilisés dans l'exécution des applications sensibles?

Je vais voir des problèmes de performances avec extraction de plusieurs instances d'objets qui ont de nombreuses relations avec d'autres objets. Je suis à l'aide de Spring et Hibernate JPA mise en œuvre avec MySQL. Le problème est que lors de l'exécution d'un APC requête, Hibernate ne fait pas automatiquement de se joindre à d'autres tables. Il en résulte n*r + 1 requêtes SQL, où n est le nombre d'objets récupérés et r est le nombre de relations.

Exemple, une Personne vit dans un discours, a beaucoup de passe-temps, et a visité de nombreux Pays:

@Entity
public class Person {
    @Id public Integer personId;    
    public String name;    
    @ManyToOne public Address address;    
    @ManyToMany public Set<Hobby> hobbies;    
    @ManyToMany public Set<Country> countriesVisited;
}

Lorsque j'effectue une JPA requête pour obtenir toutes les Personnes nommées Bob, et il y a 100 Bobs dans la base de données:

SELECT p FROM Person p WHERE p.name='Bob'

Hibernate traduit ce, 301 requêtes SQL:

SELECT ... FROM Person WHERE name='Bob'
SELECT ... FROM Address WHERE personId=1
SELECT ... FROM Address WHERE personId=2
...
SELECT ... FROM Hobby WHERE personId=1
SELECT ... FROM Hobby WHERE personId=2
...
SELECT ... FROM Country WHERE personId=1
SELECT ... FROM Country WHERE personId=2
...

Fonction de mise en veille prolongée la FAQ (ici et ici), la solution est de spécifier GAUCHE ou REJOINDRE JOINTURE EXTERNE GAUCHE (pour plusieurs-à-plusieurs) dans la requête. Alors maintenant, ma requête ressemble:

SELECT p, a, h, c FROM Person p
LEFT JOIN p.address a LEFT OUTER JOIN p.hobbies h LEFT OUTER JOIN p.countriesVisited c
WHERE p.name = 'Bob'

Cela fonctionne, mais il semble y avoir un bug si il y a plus d'une JOINTURE EXTERNE GAUCHE auquel cas Hibernate est incorrectement la recherche d'un inexistante colonne:

could not read column value from result set: personId69_2_; Column 'personId69_2_' not found.

Le bug comportement semble être éventuellement adressées par Hibernate Core bug HHH-3636. Malheureusement, le correctif n'est pas une partie de tout dégagement de Hibernate JAR. J'ai couru ma demande à l'encontre de l'instantané de construire, mais le comportement du bogue est toujours présent. J'ai également développé mon propre Hibernate Core JAR à partir du dernier code dans le référentiel et le comportement du bogue est toujours présent. Alors peut-être que HHH-3636 ne pas aborder cette question.

Ce Hibernate limitation de performances est très frustrant. Si j'ai une requête pour 1000 objets, puis 1000*r + 1, les requêtes SQL sont à la base de données. Dans mon cas, j'ai 8 les relations alors je me 8001 requêtes SQL, ce qui entraîne des performances horribles. L'officiel Hibernate solution pour cela est de gauche adhérer à toutes les relations. Mais ce n'est pas possible avec plus d'un plusieurs-à-plusieurs relations en raison du comportement du bogue. Donc je suis coincé avec left join pour plusieurs-à-un les relations et n*r+1 requêtes en raison de la plusieurs-à-plusieurs liens. J'ai l'intention de soumettre la JOINTURE EXTERNE GAUCHE problème comme Hibernate bug, mais en attendant mon client a besoin d'une application qui a de bonnes performances. J'utilise actuellement une combinaison de lot fetch (BatchSize), ehcache personnalisé et de la mise en cache en mémoire, mais la performance est encore assez pauvre (il a amélioré la récupération de 5000 objets à partir de 30 à 8 secondes). La ligne de fond est que de trop nombreuses requêtes SQL sont frapper la base de données.

Donc, mes questions, est il possible d'utiliser la mise en veille prolongée dans les performances des applications sensibles où les tables ont des relations les uns avec les autres? J'aimerais connaître le degré de succès d'Hibernate utilise l'adresse de la performance. Dois-je être écrit à la main SQL (qui quelque peu défait le but de l'utilisation d'Hibernate)? Dois-je dé-normaliser mon schéma de base de données afin de réduire le nombre de tables jointes? Ne dois-je pas l'utilisation d'Hibernate si j'en ai besoin rapidement les performances de la requête? Est-il quelque chose de plus rapide?

  • Nous avons publié Batoo JPA qui est ~15 fois plus rapide que Hibernate et met en œuvre la JPA Spec %100. La motivation principale de ce projet était tous les trois implémentations JPA sont simplement mis lent. Ayant pris conscience de JPA pourrait être beaucoup plus rapide, nous avons développé Batoo JPA. Essayer batoo.jp
InformationsquelleAutor Steve Kuo | 2009-03-16