Hibernate Tuning

2,337
-1

Published on

Published in: Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,337
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Hibernate Tuning

  1. 1. IhrePersistenzschicht?
  2. 2. Kunde, Chef, DBA?
  3. 3. Tuning vonHibernate und JPAAnwendungenMichael Plöd
  4. 4. Michael Plöd• Architekt bei Senacor Technologies AG in Nürnberg• http://www.senacor.com• michael.ploed@senacor.com• http://rockingcode.blogspot.com• Twitter: @bitboss
  5. 5. IST ORMLANGSAM
  6. 6. Zu Zu viele langsameAbfragen Abfragen Gründe für schlechte Performance Falsch Falschgetunte getunteDaten- Infra- bank struktur
  7. 7. Klassifizierung vonAnzahl der 1.500 Abfragen Abfragen 1.125 750 375 0 0 225 450 675 900 Durchschnittliche Laufzeit in [ms]
  8. 8. Ursachen Hohe Häufigkeit Hohe Laufzeit! Applikations-Logik ! Zu hohe Selektivität! Mappings ! Variablen-Übergabe! Kein Caching ! Fehlende Indizes! N+1 Selects Problem ! Karthesisches Produkt ! Locks ! Datenbankstruktur
  9. 9. N+1 Selects ProblemList list = s.createCriteria(Konto.class).list();for (Iterator it = list.iterator(); it.hasNext();) { Konto kto = (Konto) it.next(); kto.getKunde().getName();}SELECT * FROM KONTENSELECT * FROM PERSONEN WHERE PERSON_ID = ?SELECT * FROM PERSONEN WHERE PERSON_ID = ?SELECT * FROM PERSONEN WHERE PERSON_ID = ?...
  10. 10. Karthesisches Produkt@Entitypublic class Konto { ... @OneToMany(fetch=FetchType.EAGER) public Set<Buchung> getBuchungen() {...} @OneToMany(fetch=FetchType.EAGER) public Set<Vollmacht> getVollmachten() {...} ...}select konto.*, buchung.*, vollmacht.* from KONTEN konto left outer join BUCHUNGEN buchung on konto.ID = buchung.KTO_ID left outer join VOLLMACHTEN vollmacht on konto.ID = vollmacht.KTO_ID
  11. 11. Karthesisches Produktselect konto.*, buchung.*, vollmacht.* from KONTEN konto left outer join BUCHUNGEN buchung on konto.KTO_ID = buchung.KTO_ID left outer join VOLLMACHTEN vollmacht on konto.KTO_ID = vollmacht.KTO_IDKTO_ID KTO_NR ... BUCH_ID BUCH_BETRAG ... VM_ID VM_NAME ... 1 12344 ... 10 1000,00 ! ... 200 Michael Plöd ... 1 12344 ... 10 1000,00 ! ... 300 Martin Plöd ... 1 12344 ... 20 -324,23 ! ... 200 Michael Plöd ... 1 12344 ... 20 -324,23 ! ... 300 Martin Plöd ... 1 12344 ... 30 543,11 ! ... 200 Michael Plöd ... 1 12344 ... 30 543,11 ! ... 300 Martin Plöd ... 2 21300 ... 40 -4323,23 ! ... 400 Sandra Ulrich ... 2 21300 ... 40 -4323,23 ! ... 400 Melanie Ulrich ... 2 21300 ... 40 -4323,23 ! ... 400 Herbert Ulrich ... ... ... ... ... ... ... ... ... ...
  12. 12. GutesTUNINGAnzahl oder Laufzeit?istIMMEReine Frage derBALANCE
  13. 13. FETCHING CACHING ABFRAGEN! Batch ! 1st Level Cache ! Selektivität! Subselect ! 2nd Level Cache ! Query Cache! Eager ! Stateless Session ! Bind Variablen LOGIK LOCKS Runtime! Schleifen ! Optimistic ! DB Entwurf Locking! Datenmenge ! Konfiguration ! Connection Pool
  14. 14. Fetching
  15. 15. Batch Fetching@Entitypublic class Konto { SELECT k.* FROM KONTEN k @ManyToOne(...) public Person getKunde() SELECT * FROM PERSONEN {...} WHERE PERSON_ID IN (?, ?, ?, ?, ?) ...} SELECT * FROM PERSONEN WHERE PERSON_ID IN (?, ?, ?, ?, ?)@Entity@BatchSize(size=5) SELECT * FROM PERSONENpublic class Person { WHERE PERSON_ID IN (?, ?, ?) ...}
  16. 16. Batch Fetching1.500 ! Schätzung1.125 ! Einfach 750 375 ! Lazy 0 0 225 450 675 900 ! (N / Batch Size) + 1
  17. 17. Subselect Fetching@Entitypublic class Konto { SELECT k.* FROM KONTEN k @OneToMany @Fetch(FetchMode.SUBSELECT) SELECT b.* FROM BUCHUNGEN b WHERE b.KTO_ID IN ( public Set getBuchungen() SELECT k.KTO_ID FROM KONTEN k {...} ) ...}
  18. 18. Subselect Fetching1.500 ! Nur für Collections1.125 ! Keine Schätzung 750 ! Einfach 375 ! Lazy 0 0 225 450 675 900 ! 2 Abfragen
  19. 19. Eager Fetching@Entitypublic class Konto { @OneToMany( fetch = FetchType.EAGER ) SELECT ko.*, b.*, ku.* public Set getBuchungen() FROM KONTEN ko {...} LEFT OUTER JOIN BUCHUNGEN b on b.KTO_ID = ko.KTO_ID LEFT OUTER JOIN KUNDEN ku @ManyToOne( on ko.KU_ID = ku.KU_ID fetch = FetchType.EAGER ) public Kunde getEigentuemer() {...}}
  20. 20. Eager Fetching1.500 ! Nie bei 2+ Collections!1.125 ! Nicht Lazy 750 ! 1 Abfrage 375 0 ! Nie in globalen Fetch 0 225 450 675 900 Plan aufnehmen
  21. 21. Caching
  22. 22. Caching ArchitekturFirst Level Cache Persistenz Kontext A Persistenz Kontext B Persistenz Kontext CSecond Level Cache Cache Concurrency Strategy Query CacheCache Implementierung Klassen Cache Collection Cache Query Cache Region Region Region Update Timestamps Cache Region
  23. 23. Infrastruktur 1st Level Cache only Virtual Machine 1 SessionFactory Session Session Session Session Session Session
  24. 24. InfrastrukturLokale 2nd Level Caches Virtual Machine 1 SessionFactory Session Session Session Session Session Session Second Level Cache
  25. 25. Infrastruktur Lokale 2nd Level Caches Virtual Machine 1 Virtual Machine 2 SessionFactory SessionFactorySession Session Session SessionSession Session Session SessionSession Session Session Session Second Level Cache Second Level Cache
  26. 26. Infrastruktur Verteilter Second Level Cache Virtual Machine 1 Virtual Machine 2 SessionFactory SessionFactory Session Session Session Session Session Session Session Session Session Session Session Session Second Level Cache Second Level CacheNetzwerk
  27. 27. WelcheEXCEPTIONbekomme ich, wennich10.000.000 Objektelade?OutOfMemory
  28. 28. ! Hibernate verwaltet den 1st Level Cache nicht von selbst!
  29. 29. Grundregeln! ORM ist kein Batch Tool!! Bei Massen-Verarbeitung regelmässig flushen und clearen!! JDBC Batch-Size anpassenfor ( int i=0; i<100000; i++ ) { Konto konto = new Konto(...); session.save(konto); if ( i % 50 == 0 ) { session.flush(); session.clear(); }}
  30. 30. Concurrency Strategies Isolation bis zuTransactional repeatable read Isolation bis zuRead-Write read commited Keine Konsistenz Garantie, aberNonstrict-read-write TimeoutsRead-only Nur für Daten, die sich nie ändern
  31. 31. Cache Provider Nonstrict Transactional Read-write Read-only Read-write EHCache x x x OSCache x x xSwarmCache x xJBoss Cache x x
  32. 32. Konfiguration org.hibernate.cache.provider_classEHCache org.hibernate.cache.EhCacheProviderOSCache org.hibernate.cache.OsCacheProviderSwarmCache org.hibernate.cache.SwarmCacheProviderJBoss Cache org.hibernate.cache.TreeCacheProvider
  33. 33. Mappings! Annotation: @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)! XML: <cache usage=“read-write“>! Sowohl auf Klassen als auch auf Collection Level! Volles Caching: Klasse + Collection!
  34. 34. Beispiel@Entity@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)public class Author implements Serializable {... @Override public int hashCode() { ... } @Override public boolean equals(Object obj) { ... }} @Entity@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)public class RecordReview implements Article {... @OneToMany(fetch=FetchType.LAZY) @Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) private Set<Author> authors = new HashSet<Author>();...}
  35. 35. Cache Regions ! Einteilung in Cache Regions mit Naming Convention ! Cache Regions werden in Cache Provider Konfiguration referenziertKlasse Voll qualifizierter Namede.allschools.domain.Band de.allschools.domain.BandCollection Klasse + „.“ + Attributde.allschools.domain.Record#bands de.allschools.domain.Record.bands
  36. 36. EhCache Beispiel ehchache.xml<ehcache> <diskStore path="java.io.tmp"/> <defaultCache maxElementsInMemory="10000" eternal="true" overflowToDisk="true" /> <cache name="de.allschools.domain.Author" maxElementsInMemory="30" eternal="false" timeToIdleSeconds="900" timeToLiveSeconds="1800" overflowToDisk="true" /> <cache name="de.allschools.domain.RecordReview.authors" maxElementsInMemory="500" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="1200" overflowToDisk="true" /> ...</ehcache>
  37. 37. Auswahl von Caching Kandidaten?KONSERVATIV! Wenige Inserts und Updates! Viele Lesezugriffe! Unkritische Daten! Von vielen Sessions benötigt! Von vielen Usern benötigt
  38. 38. Stateless Session! sessionFactory.openStatelessSession()! Command orientierte API! Kein Persistenz Kontext! Kein Caching! Kein Transaktionales write-behind! Kein Cascading! Keine Interceptors und Events
  39. 39. Abfragen
  40. 40. Selektivität! Nur benötige Daten laden! Möglichst früh einschränken! Projection verwendenQuery query = getSession().createQuery( "select new TourCityInfo(t.name, d.timestamp, l) from Tour t inner join t.tourDates d with d.timestamp > :datum inner join d.location l where l.stadt=:stadt order by t.name asc");
  41. 41. "from User u where u.name=" + name " SQL Injection " Performance Killer " Heimtückisch
  42. 42. IMMER !Query query = BIND VARIABLEN verwendensession.createQuery("from User u where u.name= :name");q.setString("name", "michael");
  43. 43. Query Cache! Wird selten benötigt! Nur für bestimmte Queries geeignet! Wird extra konfiguriert: hibernate.cache.use_query_cache=true! Muss pro Query / Criteria aktiviert werden: query.setCacheable(true);
  44. 44. Analyse
  45. 45. Logging! Sehr detailliert, viele Informationen! Interessant sind für Tuning: # org.hibernate.jdbc - TRACE # org.hibernate.SQL - TRACE! Logging auch in User Types integrieren! Sicht auf plain SQL
  46. 46. Statistics! Müssen extra aktiviert werden! Zugriff programmatisch oder JMX
  47. 47. Datenbank + Infrastruktur ! Auch in der Datenbank analysieren # Sind alle Indizes korrekt gesetzt? # Wie ist das Laufzeitverhalten? ! Gleiches gilt für Infrastruktur # Connection Pool # Transaktions Monitor # Applikations Server
  48. 48. Laufen Messdaten lassen erheben Analyse pro Anwendungs- fall Nur eine Vergleich Tuning mit ReferenzMassnahme und Doku
  49. 49. Lasttest! Arten # Normale Last # Stresstest # Lange Lauzeiten! Setup: # Realistisches Hardware Sizing # Realistische Datenmenge
  50. 50. VIELENDANK!FRAGEN?Michael PlödSenacor Technologies AGmichael.ploed@senacor.com

×