Puffer

Die Massenoptimierung reduziert Datenbankzugriffe auf dreierlei Art:

  • Reduzierung der Anzahl von Datensätzen
  • Reduzierung der Anzahl von Spalten aus Datensätzen
  • Reduzierung der Anzahl der Datenbankzugriffe

Das Puffern von Daten aus Datenbankzugriffen kümmert sich um den letzten Punkt. Hierbei hat sie folgende zwei Effekte im Blick:

  • Kein Datensatz wird zweimal aus der Datenbank geholt
  • Im gesunden Umfang werden mehrere Datensätze im Voraus aus der Datenbank geholt ("Pre-Fetch")

Stellen wir uns eine Datenmenge as und eine dazu passende Schlüsselmenge a_keys vor. Beide besitzen einen Schlüssel key über das Schlüsselfeld key.

 

Die Funktion select_as liest für a_keys Datensätze as von der Datenbank.

 

Inkrementeller und massentauglicher Puffer

 

Für eine Menge von Schlüsseln a_keys werden Datensätze as ermittelt. Ein Puffer hält einmal gelesene Datensätze vor.

 

Der Ablauf:

 

  1. Für gleich mehrere Schlüsselwerte a_keys wird überprüft, welche Einträge der Puffer buffered_as dazu schon enthält.
  2. Für Schlüsselwerte missing_a_keys zu fehlenden Einträgen werden nun Datensätze missing_as aus der Datenbank nachbeschafft.
  3. Die Datensätze missing_as werden in den Puffer buffered_as eingefügt. 
  4. Nun können für alle Schlüsselwerte a_keys Ergebnisse r_as aus dem Puffer buffered_as ermittelt werden. 

 

Das Code-Beispiel nutzt intensiv FILTER-Ausdrücke. Diese setzen aber einen Schlüssel, hier key, voraus.

 

 

* Hole Datensätze aus Puffer

data(missing_a_keys) =
 filter #( a_keys except in buffered_as 

 using key key where key = key ) ).  

 

if lines( missing_a_keys ) > 0.

 

* Hole fehlende Datensätze aus Datenbank

   data(missing_as) = select_as( missing_a_keys ).

 

* Füge Fehlende in Puffer ein

  as = value #( base buffered_as 

   for missing_a_ in missing_as ( missing_a ) ).

 

endif.

 

* Hole nun alle Ergebnisse aus angefülltem Puffer
data(r_as) = filter #( buffered_as in a_keys 

 using key key where key = key ).

 

 

Puffer mit alternativem Schlüssel

 

Stellen wir uns nun zusätzlich Menge bs vor. Ein Einzelsatz davon ist dann b. Die Menge bs hat das Schlüsselfeld a_key und den Schlüssel a_key über dieses Feld. Weiter setzen wir voraus, dass bs für verschiedene a_key nicht doppelt kommen.

 

Die Funktion select_bs liest für a_keys Datensätze bs von der Datenbank.

 

Der Ablauf variiert nun ein wenig:

 

  1. Für gleich mehrere Schlüsselwerte a_keys wird überprüft, welche Einträge der Puffer buffered_a_keys dazu schon enthält.
  2. Für Schlüsselwerte missing_a_keys zu fehlenden Einträgen werden nun Datensätze missing_bs aus der Datenbank nachbeschafft
  3. Die Datensätze missing_bs werden in den Puffer buffered_bs eingefügt. 
  4. Die Schlüsselwerte missing_a_keys werden in den Puffer buffered_a_keys eingefügt. 
  5. Nun können für alle Schlüsselwerte a_keys Ergebnisse r_bs aus dem Puffer buffered_bs ermittelt werden. 

 

Das Beispiel hat den Charme, dass auch leere Treffermengen für bestimmte a_keys bei nochmaliger Anfrage nicht zu neuen Datenbankzugriffen führen. Der Eintrag in buffered_a_keys markiert einen bereits erfolgten Datenbankzugriff ausreichend. 

 

* Hole Datensätze aus Puffer

data(missing_a_keys) =
 filter #( a_keys except in buffered_a_keys 

 using key key where key = key ) ).  

 

if lines( missing_a_keys ) > 0.

 

* Hole fehlende Datensätze aus Datenbank

  data(missing_bs) = select_bs( missing_a_keys ).

 

* Füge Fehlende in Puffer ein

  buffered_bs = value #( base buffered_bs 

   for missing_b in missing_bs ( missing_b ) ).

 

* Füge fehlende Schlüssel in Puffer ein

 buffered_a_keys = value #( base buffered_a_keys 

 for missing_a_key IN missing_a_keys ( missing_a_key ) ).

 

endif.

 

* Hole nun alle Ergebnisse aus angefülltem Puffer
data(r_bs) = filter #( buffered_bs in a_keys 

 using key key where a_key = key ).

 

 

Puffer mit alternativem Schlüssel und doppelten Treffern

 

Stellen wir uns a_keys und bs wie oben vor. Nun betrachten wir den Sonderfall: Zwei verschiedene a_keys treffen gleiche bs.

 

Der Ablauf variiert nun erneut ein wenig:

 

  1. Für gleich mehrere Schlüsselwerte a_keys wird überprüft, welche Einträge der Puffer buffered_a_keys dazu schon enthält.
  2. Für Schlüsselwerte missing_a_keys zu fehlenden Einträgen werden nun Datensätze missing_bs aus der Datenbank nachbeschafft.
  3. Die Datensätze missing_bs werden um die bereits im Puffer buffered_bs befindlichen Einträge bereinigt zu new_bs.
  4. Die Datensätze new_bs werden in den Puffer buffered_bs eingefügt. 
  5. Die Schlüsselwerte missing_a_keys werden in den Puffer buffered_a_keys  eingefügt. 
  6. Nun können für alle Schlüsselwerte a_keys Ergebnisse r_bs aus dem Puffer buffered_bs ermittelt werden. 

 

Das Code-Beispiel nutzt wiederum intensiv FILTER-Ausdrücke.

 

* Hole Datensätze aus Puffer

data(missing_a_keys) =
 filter #( a_keys except in buffered_a_keys 

 using key key WHERE key = key ) ).  

 

if lines( missing_a_keys ) > 0.

 

* Hole fehlende Datensätze aus Datenbank

   DATA(missing_bs) = select_bs( missing_a_keys ).

 

* Ignoriere die Datensätze, die bereits im Puffer sind

  data(new_bs) =
   filter #( missing_bs except in buffered_bs 

   using key key where key = key ) ).  

 

* Füge Fehlende in Puffer ein

    buffered_bs = value #( base buffered_bs 

      for new_b IN new_bs ( new_b ) ).

 

* Füge Fehlende Schlüssel in Puffer ein

  buffered_a_keys = value #( base buffered_a_keys 

   for missing_a_key IN missing_a_keys ( missing_a_key ) ).

 

endif.

 

* Hole nun alle Ergebnisse aus angefülltem Puffer
data(r_bs) = filter #( buffered_bs IN a_keys 

 using key key key where a_key = key ).

 

Druckversion | Sitemap
© orangeclass 2017