Die Massenoptimierung reduziert Datenbankzugriffe auf dreierlei Art:
Das Puffern von Daten aus Datenbankzugriffen kümmert sich um den letzten Punkt. Hierbei hat sie folgende zwei Effekte im Blick:
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:
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:
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:
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 ).
zurück zu: Massenoptimierter Programmierstil