Query Result Caching

    Optimierung des
   Datenbankzugriffs

        Andreas Hubmer
      info@cenarion.com
         19.11.2012
Inhalt
• Problemstellung
• Tabellen-Cache
  – DBProxy
• Objekt-Cache
  – 1st-/2nd-Level Cache
  – Query Cache




                           2
Problemstellung

Application-      Application-   Application-
  Server            Server         Server




                   DB-Server


                                 Überlastung

                                                3
Lösung 1: Datenbank
            skalieren

Application-   Application-        Application-
  Server         Server              Server




                                • Synchronisation
  DB-Server         DB-Server   • 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
Query Result Caching
• Ziel
  – Hohe Cache-Hit-Rate
     • Self-Management
  – Schnelles Query-Matching
  – Konsistenz
  – Unabhängig von DB-Implementierung
• Tabellen-Cache vs. Objekt-Cache


                                        6
Tabellen-Cache: DBProxy
• Materialized-Views in lokaler DB
• Implementiert als JDBC-Treiber
                                      Query
Ergebnis                                                              Ergebnis

                           Query                             Query am Cache
           DB-Call                  nein     Treffer?   ja
                          Rewrite                              ausführen



 nein      Insert?   ja       Cache Insert
                                                                Lokale DB



                                                                                 7
DBProxy: Lokale DB
• Pro gecachter Tabelle eine lokale
  Kopie
  – horizontal und vertikal unvollständig
• Pro gecachter Join-Query eine lokale
  Tabelle




                                            8
Beispiel

Lokale Kopie einer Tabelle produkt:
Id       Preis    Anzahl
                               Q1:
1        14       8            SELECT Id, Preis, Anzahl FROM produkt
2        15       22           WHERE Preis BETWEEN 14 AND 16
5        16       13
                                  Q2:
7        NULL     18
                                  SELECT Id, Anzahl FROM produkt
8        NULL     20              WHERE Anzahl BETWEEN 10 AND 20

Im Cache:
SELECT Id FROM produkt WHERE Anzahl BETWEEN 10 AND 15


                                                                  9
Query Matching
• Gecachte Queries beschreiben Cache-
  Inhalt
• Query Containment
  – i.A. nicht lösbar
  – aber für einfache Queries entscheidbar
• Schneller: Template-basiert



                                             10
Konsistenz
• Update-Queries (update, delete, insert)
    – werden am DB-Server ausgeführt
    – werden vom DB-Server an die Proxies
      weitergegeben
•   Verzögerte Konsistenz
•   Monotone Zustandsübergänge
•   Sichtbarkeit von Updates
•   Transaktionen nicht unterstützt
                                            11
Praxis: Objekt-Cache
• Objektrelationaler Mapper (ORM)
  – Entity: Klasse, die persistiert wird
• Transaktion pro Anwendungsfall
• RAM oder Festplatte
• Wichtig: Jeder DB-Zugriff geht über
  den ORM



                                           12
Überblick
         Application Server



Transaktion      1st-Level

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

Transaktion      1st-Level




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


                                             14
1st-Level-Cache: Beispiel
Applikations-Code           Was tatsächlich geschieht
BEGIN TX                    BEGIN TX
SELECT p FROM person AS 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




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



                                            16
2nd-Level-Cache
• Pro Application Server
  – Für alle Transaktionen gemeinsam
• Ebenso ID → Objekt
• Wird befüllt beim Lesen (SELECT) und
  Commit (UPDATE, INSERT, DELETE)




                                         17
2nd-Level-Cache: Konsistenz
• Strategien:
  – Read-Only
  – Read-Write: keine serialisierbare
    Transaktion
  – Transaktional: 2PC (teuer)
• Mehrere Application-Server
  – Synchronisation wie bei verteilter DB
    (außer Read-Only)
  – Veraltete Daten, TTL setzen
                                            18
Query Cache
• SELECT … WHERE nonId=‘value‘
  – Objekt-ID notwendig für 1st/2nd-Level-
    Cache
• Schlüssel: Query
• Werte: Objekt-IDs
  – Mit diesen 1st/2nd-Level-Cache befragen
• Pro Application Server


                                              19
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
  – Viel Locking notwendig
• Synchronisation der Tabellen-
  Timestamps
                                          20
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
  – Pro Entity entscheiden
  – Performance messen (Speicherbedarf,
    Beschleunigung, DB-Entlastung)        21
Verwendungstipps (2)
• Query-Cache:
  – Nur mit 2nd-Level-Cache gemeinsam
  – Tabellen mit (fast) nur Lesezugriff
  – Bei natürlichen Schlüsseln
    (≠Primärschlüssel)
• Speicherbedarf
  – Objekte+Referenzen
• Keine direkten DB-Manipulationen per
  SQL
                                          22
Referenzen
•   [1] Khalil Amiri, Sanghyun Park, Renu Tewari, Sriram Padmanabhan: DBProxy: A dynamic
    data cache for Web applications. ICDE 2003: 821-831
•   [2] Charles Garrod, Amit Manjhi, Anastasia Ailamaki, Bruce M. Maggs, Todd C. Mowry,
    Christopher Olston, Anthony Tomasic: Scalable query result caching for web
    applications. PVLDB 1(1): 550-561 (2008)
•   [3] JPA offiziell: http://docs.oracle.com/javaee/6/tutorial/doc/bnbpy.html
•   [4] JPA Tutorial: http://en.wikibooks.org/wiki/Java_Persistence




                                                                                       23
Zusammenfassung
• Problem: DB-Überlastung
• Lösung: Caching am Application-
  Server
• Herausforderung Synchronisierung
  – Caching besonders sinnvoll bei weniger
    strikten Anforderungen
• Vorteil Objekt-Cache:
  – Näher an der Applikation – leichter zu
    steuern
• Self-Management ist eine Vision            24

Query Result Caching

  • 1.
    Query Result Caching Optimierung des Datenbankzugriffs Andreas Hubmer info@cenarion.com 19.11.2012
  • 2.
    Inhalt • Problemstellung • Tabellen-Cache – DBProxy • Objekt-Cache – 1st-/2nd-Level Cache – Query Cache 2
  • 3.
    Problemstellung Application- Application- Application- Server Server Server DB-Server Überlastung 3
  • 4.
    Lösung 1: Datenbank skalieren Application- Application- Application- Server Server Server • Synchronisation DB-Server DB-Server • 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.
    Query Result Caching •Ziel – Hohe Cache-Hit-Rate • Self-Management – Schnelles Query-Matching – Konsistenz – Unabhängig von DB-Implementierung • Tabellen-Cache vs. Objekt-Cache 6
  • 7.
    Tabellen-Cache: DBProxy • Materialized-Viewsin lokaler DB • Implementiert als JDBC-Treiber Query Ergebnis Ergebnis Query Query am Cache DB-Call nein Treffer? ja Rewrite ausführen nein Insert? ja Cache Insert Lokale DB 7
  • 8.
    DBProxy: Lokale DB •Pro gecachter Tabelle eine lokale Kopie – horizontal und vertikal unvollständig • Pro gecachter Join-Query eine lokale Tabelle 8
  • 9.
    Beispiel Lokale Kopie einerTabelle produkt: Id Preis Anzahl Q1: 1 14 8 SELECT Id, Preis, Anzahl FROM produkt 2 15 22 WHERE Preis BETWEEN 14 AND 16 5 16 13 Q2: 7 NULL 18 SELECT Id, Anzahl FROM produkt 8 NULL 20 WHERE Anzahl BETWEEN 10 AND 20 Im Cache: SELECT Id FROM produkt WHERE Anzahl BETWEEN 10 AND 15 9
  • 10.
    Query Matching • GecachteQueries beschreiben Cache- Inhalt • Query Containment – i.A. nicht lösbar – aber für einfache Queries entscheidbar • Schneller: Template-basiert 10
  • 11.
    Konsistenz • Update-Queries (update,delete, insert) – werden am DB-Server ausgeführt – werden vom DB-Server an die Proxies weitergegeben • Verzögerte Konsistenz • Monotone Zustandsübergänge • Sichtbarkeit von Updates • Transaktionen nicht unterstützt 11
  • 12.
    Praxis: Objekt-Cache • ObjektrelationalerMapper (ORM) – Entity: Klasse, die persistiert wird • Transaktion pro Anwendungsfall • RAM oder Festplatte • Wichtig: Jeder DB-Zugriff geht über den ORM 12
  • 13.
    Überblick Application Server Transaktion 1st-Level 2nd- Level DB-Server Transaktion 1st-Level Cache Transaktion 1st-Level 13
  • 14.
    1st-Level-Cache • Hash-Tabelle proEntity-Klasse • Schlüssel: Objekt-ID = Tabellenschlüssel • Werte: Objektinstanzen • Im Rahmen einer Transaktion – Kein Synchronisationsbedarf zu anderen Application-Servern 14
  • 15.
    1st-Level-Cache: Beispiel Applikations-Code Was tatsächlich geschieht BEGIN TX BEGIN TX SELECT p FROM person AS 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 15
  • 16.
    Puffer für Schreibzugriffe •Update, Insert, Delete erst mit Transaktionsende • Ausnahme: – Objekt vom Typ A wurde verändert: Vor einer DB-Query über A müssen die Änderungen persistiert werden – Manueller Flush 16
  • 17.
    2nd-Level-Cache • Pro ApplicationServer – Für alle Transaktionen gemeinsam • Ebenso ID → Objekt • Wird befüllt beim Lesen (SELECT) und Commit (UPDATE, INSERT, DELETE) 17
  • 18.
    2nd-Level-Cache: Konsistenz • Strategien: – Read-Only – Read-Write: keine serialisierbare Transaktion – Transaktional: 2PC (teuer) • Mehrere Application-Server – Synchronisation wie bei verteilter DB (außer Read-Only) – Veraltete Daten, TTL setzen 18
  • 19.
    Query Cache • SELECT… WHERE nonId=‘value‘ – Objekt-ID notwendig für 1st/2nd-Level- Cache • Schlüssel: Query • Werte: Objekt-IDs – Mit diesen 1st/2nd-Level-Cache befragen • Pro Application Server 19
  • 20.
    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 – Viel Locking notwendig • Synchronisation der Tabellen- Timestamps 20
  • 21.
    Verwendungstipps (1) • Zuerstandere Optimierungen (zB: Indizes) • 1st-Level-Cache ist immer aktiv • 2nd-Level-Cache: – Wenn viele Lesezugriffe vorkommen – Veraltete Daten ohne Transaktionsunterstützung – Pro Entity entscheiden – Performance messen (Speicherbedarf, Beschleunigung, DB-Entlastung) 21
  • 22.
    Verwendungstipps (2) • Query-Cache: – Nur mit 2nd-Level-Cache gemeinsam – Tabellen mit (fast) nur Lesezugriff – Bei natürlichen Schlüsseln (≠Primärschlüssel) • Speicherbedarf – Objekte+Referenzen • Keine direkten DB-Manipulationen per SQL 22
  • 23.
    Referenzen • [1] Khalil Amiri, Sanghyun Park, Renu Tewari, Sriram Padmanabhan: DBProxy: A dynamic data cache for Web applications. ICDE 2003: 821-831 • [2] Charles Garrod, Amit Manjhi, Anastasia Ailamaki, Bruce M. Maggs, Todd C. Mowry, Christopher Olston, Anthony Tomasic: Scalable query result caching for web applications. PVLDB 1(1): 550-561 (2008) • [3] JPA offiziell: http://docs.oracle.com/javaee/6/tutorial/doc/bnbpy.html • [4] JPA Tutorial: http://en.wikibooks.org/wiki/Java_Persistence 23
  • 24.
    Zusammenfassung • Problem: DB-Überlastung •Lösung: Caching am Application- Server • Herausforderung Synchronisierung – Caching besonders sinnvoll bei weniger strikten Anforderungen • Vorteil Objekt-Cache: – Näher an der Applikation – leichter zu steuern • Self-Management ist eine Vision 24