Zum Hauptinhalt springen

Performante Lookups in BW Transformationen - Die Nutzung interner Tabellen vs. SELECTS aus der HANA-Datenbank

In dieser Serie wollen wir uns mit Implementierungstechniken für Lookups auseinandersetzen, bei denen jeder Datensatz der zu durchsuchenden Tabelle überprüft werden sollte. Je größer unsere Datenpakete und unsere Lookup-Tabellen, desto wichtiger ist eine performante Implementierung.

Weil man in BW-Transformationen normalerweise Datenpakete mit einer Größe von 50.000 oder mehr Datensätzen verarbeitet, ist es nicht zu empfehlen, einzelne SELECT-Anweisungen innerhalb der LOOP-Schleife in ABAP-Routinen durchzuführen. Dies würde dazu führen, dass für jeden Datensatz aus dem Datenpaket eine Datenbankselektion durchgeführt wird. Auch wenn man eine schnelle In-Memory-Datenbank wie SAP HANA hat, geschieht das Nachlesen von Millionen Datensätzen daraus nicht automatisch blitzschnell. Dies liegt auch an dem Overhead, der bei jedem einzelnen Zugriff entsteht. Besser ist es, vor der LOOP-Schleife der Transformation die relevanten Daten mit einer oder wenigen SELECT-Statements in internen Tabellen zu speichern und diese später mit der READ-Anweisung auszulesen. Am besten sollte man dafür Hash-Tabellen verwenden.

 Ob man dann mehrere SELECT-Anweisungen pro Datenpaket (1) durchführt …

SELECT
    key_field1
    key_field2
    key_field3

    group_field
    lookup_field

FROM dbTab INTO TABLE itab_group1
FOR ALL ENTRIES IN result_package
WHERE key_field1 = result_package-key_field1
  AND key_field2 = result_package-key_field2

  AND key_field3 = result_package-key_field3
  AND group_field = 'GR1'.

 "Bei Bedarf Sortierung/Aggregation/Reduktion der Felder on itab_group1 implementieren

SELECT

    key_field1
    key_field2
    key_field3 
  
    group_field
    lookup_field

FROM dbTab INTO TABLE itab_group2
FOR ALL ENTRIES IN result_package
WHERE key_field1 = result_package-key_field1
  AND key_field2 = result_package-key_field2

  AND key_field3 = result_package-key_field3
  AND group_field = 'GR2'.

 "Bei Bedarf Sortierung/Aggregation/Reduktion der Felder on itab_group1 implementieren

… oder eine SELECT-ENDSELECT-Schleife (2) nutzt, um mehrere interne Tabellen zu befüllen, ist an der Stelle für die Geschwindigkeit unerheblich. 

SELECT
    key_field1
    key_field2
    key_field3

    group_field
    lookup_field
FROM dbTab INTO ls_all

FOR ALL ENTRIES IN result_package

WHERE key_field1 = result_package-key_field1
 AND key_field2 = result_package-key_field2

 AND key_field3 = result_package-key_field3
 AND ( group_field = 'GR1'

 OR group_field = 'GR2')

 AND NOT lookup_date = '00000000'.

CASE ls_rest_plus-group_field.

  WHEN 'GR1'.

    IF itab_group1 IS INITIAL.

 "Ab diesem Punkt ist das Feld mit der Gruppe nicht mehr wichtig => ergo geben wir nur die restlichen Zeilen weiter

      MOVE-CORRESPONDING ls_all TO ls_group.

    INSERT ls_group INTO TABLE itab_group1.
     
   ELSE.
    READ TABLE itab_group1
      WITH TABLE KEY key_field1 = ls_group-key_field1
         key_field2 = ls_group-key_field2
         key_field3 = ls_group-key_field3
    ASSIGNING <fs_group>.

 IF sy-subrc = 0.

 "Bei Bedarf Aktualisierung der Zeile von itab_group1 implementieren

    ELSE.
      MOVE-CORRESPONDING ls_all TO ls_group.

      INSERT ls_group INTO TABLE itab_group1.

     ENDIF.
     ENDIF.

 WHEN OTHERS.

 "Wie oben, aber für itab_group2

 ENDCASE.
 CLEAR ls_all.
 CLEAR ls_group.
 UNASSIGN <fs_group>.
ENDSELECT.

Bei einem DTP mit Paketgröße 200.000 und knapp 16 Mio. zu beladenden Datensätzen haben wir mit (1) 43 m 39 s und mit (2) 42 m 25 s gebraucht. Dabei haben wir aus einer Tabelle mit knapp 190 Mio. Datensätzen nachgelesen und müssten insgesamt 5 Gruppen von Daten in internen Tabellen aufbauen, die beim Lookup in der LOOP-Schleife der Transformation durchgesucht werden mussten. Und ja, diese Beladungen wurden auf BW on HANA durchgeführt. 

Zum Vergleich, wenn wir an der Stelle bei den 5 Lookups innerhalb der LOOP-Schleife aus der Datenbank nachlesen würden, würden wir für die Beladung derselben Datenmenge ca. 5 Stunden verbrauchen.

Dass die Methoden (1) und (2) vergleichbar schnell laufen, bestätigt auch die These (Kapitel 4.4.2), dass der gängige schlechte Ruf von SELECT-ENDSELECT-Schleifen nicht gerechtfertigt ist. Diese haben zwar gewisse Nachteile, performancetechnisch sind sie aber nicht unbedingt langsamer als SELECT-INTO-Statements. Vor allem, wenn man dadurch eine einfachere und besser nachvollziehbare Programmierlogik aufbauen kann, sollten diese bevorzugt werden. Bei In-Memory-Datenbanken werden die Nachteile von SELECT-ENDSELECT-Schleifen irrelevanter.

Wenn man auch noch darauf achtet, nur die Datensätze und Felder zu selektieren, die man später benötigt, kann man sich in der Regel auch auf performante Transformationen freuen. Der Implementierungsaufwand an der Stelle lohnt sich!