DB-Caching
                  Optimierung des
                  Datenbankzugriffs


andreas.hubmer@cenarion.com           15.04.2013
Inhalt

Problemstellung
1st-Level Cache
                      JPA
2nd-Level Cache    Hibernate
                    Ehcache
 Query Cache
      Tipps


                               2
Problemstellung

Application-      Application-   Application-
  Server            Server         Server




                      DB




                                                3
Lösung 1: Datenbank skalieren

 Application-   Application-      Application-
   Server         Server            Server




                               • Synchronisation
       DB                DB    • Lizenzen




                                                   4
Lösung 2: Caching

Application-       Application-      Application-
  Server             Server            Server
 DB-Cache           DB-Cache          DB-Cache




                                  • Entlastet DB
                    DB-Server     • Beschleunigt Zugriff




                                                           5
Ziele

• Hohe Cache-Hit-Rate

• Konsistenz

• Self-Management?



                        6
Objekt-Cache
• Objektrelationaler Mapper (ORM)
  – Entity
• Transaktion pro Anwendungsfall
• RAM oder Festplatte
• Wichtig: Jeder DB-Zugriff geht über den
  ORM



                                            7
1st-Level-Cache

         Application Server




Transaktion     1st-Level-Cache   DB-Server




                                              8
1st-Level-Cache
•   Hash-Tabelle pro Entity-Klasse
•   Schlüssel: Objekt-ID = Primary Keys
•   Werte: Objektinstanzen
•   Im Rahmen einer Transaktion
    – Kein Synchronisationsbedarf zu anderen
      Application-Servern




                                               9
1st-Level-Cache: Beispiel
Applikations-Code           Was tatsächlich geschieht
BEGIN TX                    BEGIN TX
SELECT p FROM person AS p   p = SELECT * FROM person
          WHERE p.id=1               WHERE id=1
                            personCache.put(1, p)

SELECT p FROM person AS p   personCache.get(1)
       WHERE p.id=1
p.setFirma(“Cenarion“)

END TX                      UPDATE person SET firma=…
                            END TX




                                                        10
Puffer für Schreibzugriffe
• Update, Insert, Delete erst mit
  Transaktionsende
• Ausnahmen:
  – Manueller Flush
  – Objekt vom Typ A wurde verändert: Vor einer
    DB-Query über A müssen die Änderungen an
    A persistiert werden



                                              11
Mit der JPA
@Stateless
public class MyEjb {

    @PersistenceContext
    private EntityManager entityManager;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void businessMethod() throws Exception {
      Person p = entityManager.find(Person.class, 1);
      p.setFirma(“Cenarion“);
    }
}



                                                               12
2nd-Level-Cache

         Application Server



Transaktion      1st-Level

                               2nd-
                              Level   DB-Server
Transaktion      1st-Level
                              Cache

Transaktion      1st-Level




                                                  13
2nd-Level-Cache
• Pro Application Server einer
  – für alle Transaktionen gemeinsam
• Cache über Objekt-Ids
• Werte statt Objekte
• Wird befüllt beim Lesen (SELECT) und
  Commit (UPDATE, INSERT, DELETE)



                                         14
2nd-Level-Cache: Konsistenz

Strategien:
• Read-Only
• Nonstrict Read-Write
• Read-Write: ohne serialisierbare
  Transaktionen
• Transaktional: 2PC (teuer)


                                     15
2nd-Level-Cache: Konsistenz


Mehrere Application-Server:
• Synchronisation wie bei verteilter DB
  (außer Read-Only)
• Veraltete Daten, TTL setzen




                                          16
Wie einrichten (JPA)?
persistence.xml

<persistence-unit name="myUnit" transaction-type="JTA">
  …
  <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
     <!– NONE, DISABLE_SELECTIVE -->
</persistence-unit>


@javax.persistence.Entity
@javax.persistence.Cacheable(true)
public class Person {
  ….
}



                                                            17
JPA im Rückstand




                   18
Wie einrichten (Hibernate)?
persistence.xml

…
<property name="hibernate.cache.use_second_level_cache"
value="true" />
<property name="hibernate.cache.region.factory_class"
value="net.sf.ehcache.hibernate.EhCacheRegionFactory" />


@javax.persistence.Entity
@org.hibernate.annotations.Cache(usage=
     CacheConcurrencyStrategy.READ_WRITE)
public class Person {

}


                                                           19
Wie einrichten (Ehcache)?
ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"
         updateCheck="false">
         <cache
                  name="com.cenarion.Person"
                  maxElementsInMemory="200"
                  eternal="false"
                  timeToIdleSeconds="600"
                  timeToLiveSeconds="3600"
                  overflowToDisk="false"
                  />
</ehcache>




                                                                 20
Cache API
Cache c = entityManager.getEntityManagerFactory().getCache()




javax.persistence.          evict(clazz)
      Cache




                                                               21
Query Cache

         Application Server



Transaktion      1st-Level     2nd-
                              Level
                              Cache
                                       DB-Server
Transaktion      1st-Level
                              Query-
                              Cache
Transaktion      1st-Level




                                                   22
Query Cache
• ID notwendig für 1st/2nd Level Cache
        SELECT … WHERE nonId=‘value‘

• Schlüssel: Query
• Werte: Objekt-IDs
  – Mit diesen wird der 1st/2nd-Level-Cache
    befragt



                                              23
Query Cache: Konsistenz
• Bei Änderungen an einer Tabelle A werden
  alle gecachten Ergebnisse für Queries
  über A ungültig
• Mittels Timestamp
  – Timestamp pro Tabelle und gecachter Query
  – Locking notwendig
• Synchronisation der Tabellen-Timestamps


                                                24
Beispiel (1)
      SELECT p FROM Person p WHERE plz=‘1041 ‘


                                         4
                          3    2nd-
                              Level
                 2            Cache
Transaktion   1st-Level                      DB-Server
                              Query-
                              Cache
                          1




                                                         25
Beispiel (2)
                      p.setPLZ(‘1040‘)



                             2nd-
                            Level
                  1         Cache
Transaktion   1st-Level                  DB-Server
                            Query-
                            Cache




                                                     26
Beispiel (3)
                          COMMIT


                                       2
                          3    2nd-
                              Level
                 1            Cache
Transaktion   1st-Level                    DB-Server
                              Query-
                              Cache




                                                       27
Query Cache: Config

ehcache.xml

<cache   name="org.hibernate.cache.StandardQueryCache"
         maxElementsInMemory="200"
         … />

<cache   name="org.hibernate.cache.UpdateTimestampsCache"
         maxElementsInMemory="1000"
         eternal="true"
         overflowToDisk="false"/>




                                                            28
Hibernate

• Cache Providers
• Collections (@Cache)
• Regions




                         29
Verwendungstipps (1)
• Zuerst andere Optimierungen (zB: Indizes)
• 1st-Level-Cache ist immer aktiv
• 2nd-Level-Cache:
  – Wenn viele Lesezugriffe vorkommen
  – Veraltete Daten ohne
    Transaktionsunterstützung kein Problem
  – Pro Entity entscheiden
  – Performance messen (#Hits, Beschleunigung,
    Speicherbedarf, DB-Entlastung)
                                             30
Verwendungstipps (2)
• Query-Cache:
  – Für einzelne Queries per Hint aktivieren
  – Nur mit 2nd-Level-Cache gemeinsam
  – Tabellen mit (fast) nur Lesezugriff
  – Bei natürlichen Schlüsseln (≠Primärschlüssel)
• Keine direkten DB-Manipulationen per
  SQL/Native Query


                                                31
32
Application Server


            2nd-Level Cache | Query Cache



Application Server                  Sync



  Transaktion        1st-Level    2nd-
                                 Level
                                 Cache
                                            DB-Server
  Transaktion        1st-Level
                                 Query-
                                 Cache
  Transaktion        1st-Level




                                                        33
Zusammenfassung
• Problem: DB-Überlastung
• Lösung: Caching am Application-Server
• Herausforderung Synchronisierung
  – Caching besonders sinnvoll bei weniger
    strikten Anforderungen
• Self-Management ist eine Vision



                                             34
Links
•   JPA offiziell: http://docs.oracle.com/javaee/6/tutorial/doc/bnbpy.html
•   JPA Tutorial: http://en.wikibooks.org/wiki/Java_Persistence
•   JPA: https://blogs.oracle.com/carolmcdonald/entry/jpa_caching
•   Hibernate: http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/performance.html
•   Hibernate, alt, aber gut: http://www.javalobby.org/java/forums/t48846.html




                                                                                               35

Datenbankoptimierung

  • 1.
    DB-Caching Optimierung des Datenbankzugriffs andreas.hubmer@cenarion.com 15.04.2013
  • 2.
    Inhalt Problemstellung 1st-Level Cache JPA 2nd-Level Cache Hibernate Ehcache Query Cache Tipps 2
  • 3.
    Problemstellung Application- Application- Application- Server Server Server DB 3
  • 4.
    Lösung 1: Datenbankskalieren Application- Application- Application- Server Server Server • Synchronisation DB DB • Lizenzen 4
  • 5.
    Lösung 2: Caching Application- Application- Application- Server Server Server DB-Cache DB-Cache DB-Cache • Entlastet DB DB-Server • Beschleunigt Zugriff 5
  • 6.
    Ziele • Hohe Cache-Hit-Rate •Konsistenz • Self-Management? 6
  • 7.
    Objekt-Cache • Objektrelationaler Mapper(ORM) – Entity • Transaktion pro Anwendungsfall • RAM oder Festplatte • Wichtig: Jeder DB-Zugriff geht über den ORM 7
  • 8.
    1st-Level-Cache Application Server Transaktion 1st-Level-Cache DB-Server 8
  • 9.
    1st-Level-Cache • Hash-Tabelle pro Entity-Klasse • Schlüssel: Objekt-ID = Primary Keys • Werte: Objektinstanzen • Im Rahmen einer Transaktion – Kein Synchronisationsbedarf zu anderen Application-Servern 9
  • 10.
    1st-Level-Cache: Beispiel Applikations-Code Was tatsächlich geschieht BEGIN TX BEGIN TX SELECT p FROM person AS p p = SELECT * FROM person WHERE p.id=1 WHERE id=1 personCache.put(1, p) SELECT p FROM person AS p personCache.get(1) WHERE p.id=1 p.setFirma(“Cenarion“) END TX UPDATE person SET firma=… END TX 10
  • 11.
    Puffer für Schreibzugriffe •Update, Insert, Delete erst mit Transaktionsende • Ausnahmen: – Manueller Flush – Objekt vom Typ A wurde verändert: Vor einer DB-Query über A müssen die Änderungen an A persistiert werden 11
  • 12.
    Mit der JPA @Stateless publicclass MyEjb { @PersistenceContext private EntityManager entityManager; @TransactionAttribute(TransactionAttributeType.REQUIRED) public void businessMethod() throws Exception { Person p = entityManager.find(Person.class, 1); p.setFirma(“Cenarion“); } } 12
  • 13.
    2nd-Level-Cache Application Server Transaktion 1st-Level 2nd- Level DB-Server Transaktion 1st-Level Cache Transaktion 1st-Level 13
  • 14.
    2nd-Level-Cache • Pro ApplicationServer einer – für alle Transaktionen gemeinsam • Cache über Objekt-Ids • Werte statt Objekte • Wird befüllt beim Lesen (SELECT) und Commit (UPDATE, INSERT, DELETE) 14
  • 15.
    2nd-Level-Cache: Konsistenz Strategien: • Read-Only •Nonstrict Read-Write • Read-Write: ohne serialisierbare Transaktionen • Transaktional: 2PC (teuer) 15
  • 16.
    2nd-Level-Cache: Konsistenz Mehrere Application-Server: •Synchronisation wie bei verteilter DB (außer Read-Only) • Veraltete Daten, TTL setzen 16
  • 17.
    Wie einrichten (JPA)? persistence.xml <persistence-unitname="myUnit" transaction-type="JTA"> … <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <!– NONE, DISABLE_SELECTIVE --> </persistence-unit> @javax.persistence.Entity @javax.persistence.Cacheable(true) public class Person { …. } 17
  • 18.
  • 19.
    Wie einrichten (Hibernate)? persistence.xml … <propertyname="hibernate.cache.use_second_level_cache" value="true" /> <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory" /> @javax.persistence.Entity @org.hibernate.annotations.Cache(usage= CacheConcurrencyStrategy.READ_WRITE) public class Person { } 19
  • 20.
    Wie einrichten (Ehcache)? ehcache.xml <ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd" updateCheck="false"> <cache name="com.cenarion.Person" maxElementsInMemory="200" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="3600" overflowToDisk="false" /> </ehcache> 20
  • 21.
    Cache API Cache c= entityManager.getEntityManagerFactory().getCache() javax.persistence. evict(clazz) Cache 21
  • 22.
    Query Cache Application Server Transaktion 1st-Level 2nd- Level Cache DB-Server Transaktion 1st-Level Query- Cache Transaktion 1st-Level 22
  • 23.
    Query Cache • IDnotwendig für 1st/2nd Level Cache SELECT … WHERE nonId=‘value‘ • Schlüssel: Query • Werte: Objekt-IDs – Mit diesen wird der 1st/2nd-Level-Cache befragt 23
  • 24.
    Query Cache: Konsistenz •Bei Änderungen an einer Tabelle A werden alle gecachten Ergebnisse für Queries über A ungültig • Mittels Timestamp – Timestamp pro Tabelle und gecachter Query – Locking notwendig • Synchronisation der Tabellen-Timestamps 24
  • 25.
    Beispiel (1) SELECT p FROM Person p WHERE plz=‘1041 ‘ 4 3 2nd- Level 2 Cache Transaktion 1st-Level DB-Server Query- Cache 1 25
  • 26.
    Beispiel (2) p.setPLZ(‘1040‘) 2nd- Level 1 Cache Transaktion 1st-Level DB-Server Query- Cache 26
  • 27.
    Beispiel (3) COMMIT 2 3 2nd- Level 1 Cache Transaktion 1st-Level DB-Server Query- Cache 27
  • 28.
    Query Cache: Config ehcache.xml <cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="200" … /> <cache name="org.hibernate.cache.UpdateTimestampsCache" maxElementsInMemory="1000" eternal="true" overflowToDisk="false"/> 28
  • 29.
    Hibernate • Cache Providers •Collections (@Cache) • Regions 29
  • 30.
    Verwendungstipps (1) • Zuerstandere Optimierungen (zB: Indizes) • 1st-Level-Cache ist immer aktiv • 2nd-Level-Cache: – Wenn viele Lesezugriffe vorkommen – Veraltete Daten ohne Transaktionsunterstützung kein Problem – Pro Entity entscheiden – Performance messen (#Hits, Beschleunigung, Speicherbedarf, DB-Entlastung) 30
  • 31.
    Verwendungstipps (2) • Query-Cache: – Für einzelne Queries per Hint aktivieren – Nur mit 2nd-Level-Cache gemeinsam – Tabellen mit (fast) nur Lesezugriff – Bei natürlichen Schlüsseln (≠Primärschlüssel) • Keine direkten DB-Manipulationen per SQL/Native Query 31
  • 32.
  • 33.
    Application Server 2nd-Level Cache | Query Cache Application Server Sync Transaktion 1st-Level 2nd- Level Cache DB-Server Transaktion 1st-Level Query- Cache Transaktion 1st-Level 33
  • 34.
    Zusammenfassung • Problem: DB-Überlastung •Lösung: Caching am Application-Server • Herausforderung Synchronisierung – Caching besonders sinnvoll bei weniger strikten Anforderungen • Self-Management ist eine Vision 34
  • 35.
    Links • JPA offiziell: http://docs.oracle.com/javaee/6/tutorial/doc/bnbpy.html • JPA Tutorial: http://en.wikibooks.org/wiki/Java_Persistence • JPA: https://blogs.oracle.com/carolmcdonald/entry/jpa_caching • Hibernate: http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/performance.html • Hibernate, alt, aber gut: http://www.javalobby.org/java/forums/t48846.html 35