Kann Hibernate in leistungsempfindlichen Anwendungen verwendet werden?

Sehe ich performance-Probleme mit dem abrufen von mehreren Instanzen von Objekten, die viele Beziehungen zu anderen Objekten. Ich bin mit Spring und Hibernate - JPA-Implementierung mit MySQL. Das Problem ist, dass bei der Ausführung einer JPA-query, Hibernate nicht automatisch an andere Tische. Dies ergibt n*r + 1 SQL-Abfragen, wobei n die Anzahl der Objekte, die abgefragt werden, und r ist die Anzahl der Beziehungen.

Beispiel eine Person lebt, an eine Adresse, hat viele Hobbys, und besuchte viele Länder:

@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;
}

Wenn ich eine JPA-query, um alle Personen, die mit Namen Bob, und es gibt 100 Bobs in der Datenbank:

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

Hibernate übersetzt, 301 SQL-Abfragen:

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
...

Entsprechend der Hibernate FAQ (hier und hier), die Lösung ist, um anzugeben, LEFT JOIN-oder LEFT OUTER JOIN (die für viele-zu-viele) in der Abfrage. So nun meine Abfrage sieht wie folgt aus:

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'

Dies funktioniert, aber es scheint ein Fehler zu sein, wenn es mehr als eine LEFT OUTER JOIN in diesem Fall Hibernate ist falsch auf der Suche für eine nicht-existente Säule:

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

Fehler Verhalten erscheint, die möglicherweise angesprochen Hibernate Core bug HHH-3636. Leider ist die Fehlerbehebung ist nicht Teil von jedem veröffentlicht Hibernate JAR. Ich habe meine Bewerbung vor der snapshot-build, aber das Fehler-Verhalten ist immer noch vorhanden. Ich habe auch gebaut, meine eigene Hibernate-Core-JAR von den neuesten code in das repository und das Fehler-Verhalten ist immer noch vorhanden. Also vielleicht HHH-3636 nicht dieses.

Diese Hibernate performance-Einschränkung ist sehr frustrierend. Wenn ich die Abfrage für 1000 Objekte dann 1000*r + 1 SQL-Abfragen an der Datenbank vorgenommen werden. In meinem Fall habe ich 8 Beziehungen also ich bekomme 8001 SQL-Abfragen, die Ergebnisse in schreckliche Leistung. Die offizielle Hibernate-Lösung ist left join alle Beziehungen. Aber dies ist nicht möglich mit mehr als einer viele-zu-viele-Beziehungen aufgrund der Fehler-Verhalten. So bin ich stecken mit der linken schließt sich für viele-zu-eins-Beziehungen und n*r+1 Abfragen durch die viele-zu-viele-Beziehungen. Ich plan Einreichen, den LEFT-OUTER-JOIN-problem ist wie ein Hibernate-bug, aber in der Zwischenzeit mein Kunde braucht eine app, die hat eine angemessene Leistung. Derzeit benutze ich eine Kombination von batch fetch (BatchSize), ehcache und benutzerdefinierte in-memory-caching, aber die Leistung ist noch ziemlich schlecht (es verbessert abrufen 5000 Objekte von 30 bis 8 Sekunden). Die Quintessenz ist, dass zu viele SQL-Abfragen auf die Datenbank.

So, meine Fragen, ist es möglich, Überwintern in der performance-sensitive Anwendungen, bei denen Tabellen haben mehrfache Beziehungen zu einander? Ich würde gerne hören, wie erfolgreich Hibernate verwendet-Adresse der Leistung. Sollte ich von hand schreiben von SQL (was irgendwie Niederlagen der Zweck der Verwendung von Hibernate)? Sollte ich de-normalisieren mein Datenbank-schema zu reduzieren, die Anzahl der verknüpften Tabellen? Sollte ich nicht mit Hibernate, wenn ich brauche eine schnelle Abfrageleistung? Gibt es etwas schnellere?

InformationsquelleAutor der Frage Steve Kuo | 2009-03-16

Schreibe einen Kommentar