Massenoptimierung

Es geht bei der Massenoptimierung um Abbildungen von Mengen auf Mengen - in SAP ABAP sind hier vor allem Datenbank- und interne Tabellen gemeint. Die Optimierung gelingt nur, wenn man die Verarbeitung von Mengen konsequent durchzieht - dies gilt für Datenbankabfragen und -updates, für Aufrufe und Unteraufrufe, für Meldungen, für die Fehlerbehandlung. Wie dies aussehen kann, sei hier in Beispielen erklärt. 

 

Stellen wir uns eine Eingangsmenge as und daraus ableitbare Mengen bs bis es vor. Einzelsätze davon sind dann a bis e. Während as einen Schlüssel key über das Schlüsselfeld key besitzt, haben die anderen das Schlüsselfeld a_key und den Schlüssel a_key über dieses Feld. Entsprechende Datentypen sind ty_<x>.

 

Funktionen select_<x> lesen das Jeweilige von der Datenbank. Funktionen create_<X> erzeugen hier aus den gegebenen Einzelsätzen Ergebnisse, der Einfachheit halber wiederum als Einzelsatz.

 

Klassisches Vorgehen

 

Ein üblicher Aufbau einer Funktion mit Abbildung von Menge auf Menge ist folgender:

data(as) = select_as( ).

data ds type ty_ds. "Ergebnis
loop at as into data(a).
  data(b) = select_b( a-key ).
  data(c) = select_c( a-key ).

  data(d) = create_d( a, b, c ).
  ds = value #( base ds ( d ) ).
loop.

Während eine Menge von as vorab beschafft wird, erfolgen für b und c zeitintensive Einzelabfragen. Dies muss nicht, wie hier, auffällig innerhalb der gleichen Code-Strecke passieren. Vielmehr erfolgen solche Einzelabfragen häufiger einige Aufrufe tiefer. Beginnt man nur einmal mit einer Einzelabfrage, kommt man bei tieferen Aufrufen nicht mehr davon los.

 

Mengenorientierte Datenbeschaffung

 

Im massenoptimierten Ansatz werden alle Eingangsgrößen, soweit möglich, als Menge vorab beschafft - insbesondere, wenn die Beschaffung über Datenbankanfragen geht. Dabei sollte gelten, dass eine mengenorientierte Funktion ebenfalls nur mengenorientierte Funktionen ruft.

 

Findet dann doch per Schleife eine Einzelsatzverarbeitung statt, können als Eingangswert Einzelsätze passend aus der jeweils vorausbeschafften Menge ermittelt werden. Im Beispiel: Einzelsätze werden aus den vorab beschafften internen Tabellen mittels Tabellenausdrücke aus ABAP 7.40 ermittelt. Hier hilft ein passender Schlüssel bei der Optimierung.

 

Das Ergebnis aus der Schleife sollte wieder eine Menge sein. Das Verhalten der Schleife kommt nach außen hin einer mengenorientierten Verarbeitung gleich.

data(as)     = select_as( ).
data(a_keys) = get_a_keys( as ).
data(bs)     = select_bs( a_keys ).
data(cs)     = select_cs( a_keys ).

data ds type ty_ds. "Ergebnis
loop at as into data(a).
  data(b) = bs[ key a_key components a_key = a-key ].
  data(c) = cs[ key a_key components a_key = a-key ].
  data(d) = create_d( a, b, c ).
  ds = value #( base ds ( d ) ).
loop.

Wechsel von Schleifen und Mengenverarbeitungen

 

Sind Schleifen zu Durchführung von Zwischenschritten geeigneter oder gar notwendig, können diese abschnittsweise und im Wechsel mit Mengenfunktionen eingesetzt werden. Im Beispiel: Der Aufwand, dass für as eine Schleife zweimal durchlaufen wird, ist vernachlässigbar gegenüber dem Vorteil, den eine Bündelung der Datenbankabfrage von ds bringt.

data(as)     = select_as( ).
data(a_keys) = get_a_keys( as ).
data(bs)     = select_bs( a_keys ).
data(cs)     = select_cs( a_keys ).

data d_keys type ty_d_keys. "Zwischenergebnis
loop at as into data(a).
  data(b) = bs[ key a_key components a_key = a-key ].
  data(c) = cs[ key a_key components a_key = a-key ].
  data(d_key) = create_d_key( a, b, c ).
  d_keys = value #( base d_keys ( d_key ) ).
endloop. 

data(ds) = select_ds( d_keys ).
data es     type ty_es.     "Ergebnis
loop at as into data(a).  
  data(b) = bs[ key a_key components a_key = a-key ].
  data(b) = cs[ key a_key components a_key = a-key ].
  data(c) = ds[ key a_key components a_key = a-key ].

  data(e) = create_e( a, b, c, d ).
  es = value #( base es ( e ) ).
endloop.

Von der Schleife zur Mengenverarbeitung

 

Mit neueren Sprachmitteln kann die Einzelverarbeitung per Schleife oft in eine Mengenverarbeitung überführt werden. Im Beispiel: Hier werden die neuen Konstruktorausdrücke von ABAP 7.40 verwendet. Auch hier helfen passende Schlüssel bei der Optimierung.

data(as)     = select_as( ).
data(a_keys) = get_a_keys( as ).
data(bs)     = select_bs( a_keys ).
data(cs)     = select_cs( a_keys ).
data(d_keys) = value ty_d_keys(
  for a in as
  for b in bs using key a_key where ( b-a_key = a-key )  
  for c in cs using key a_key where ( c-a_key = a-key )
  ( create_d_key( a, b, c ) ) ).

data(ds) = select_ds( d_keys ).

data(es) = value ty_es(
  for a in as
  for b in bs using key a_key where ( b-a_key = a-key )
  for c in cs using key a_key where ( c-a_key = a-key )
  for d in ds using key a_key where ( d-a_key = a-key )
  ( create_e( a, b, c, d ) ) ).

Ist für b, c oder d jeweils nur ein passender Satz zu erwarten, eignet sich folgende alternative Schreibweise. Sie nutzt Zwischenergebnisse mit dem Zusatz LET.

 

Mit dem Zusatz OPTIONAL kann auch die Situation verkraftet werden, dass es für bc oder jeweils keine Ergebnisse geben kann. Es wird in diesem Falle ein initialer Satz verwendet. Dies kommt dann in etwa einem LEFT OUTER JOIN gleich. 

data(as)     = select_as( ).
data(a_keys) = get_a_keys( as ).
data(bs)     = select_bs( a_keys ).
data(cs)     = select_cs( a_keys ).
data(d_keys) = value ty_d_keys(
  for a in as
  let
    b = bs[ key a_key components a_key = a-key optional ]  
    c = cs[ key a_key components a_key = a-key optional ]
  in
  ( create_d_key( a, b, c ) ) ).

data(ds) = select_ds( d_keys ).

data(es) = value ty_es(
  for a in as
  let
    b = bs[ key a_key components a_key = a-key optional ]
    c = cs[ key a_key components a_key = a-key optional ]
    d = ds[ key a_key components a_key = a-key optional ]
  in 
  ( create_e( a, b, c, d ) ) ).
Druckversion | Sitemap
© orangeclass 2017