Prüfung kritischer Objekte / Critical Objects Check – Performanceoptimierung

Manchmal zweifle ich.

Nutzt überhaupt irgend jemand den SAP Solution Manager?

Gerade habe ich die Funktion „Prüfung kritischer Objekte / Critical Objects Check“ für 50.000 Objektdefinitionen getestet. Die Laufzeit von mehr als 10 Minuten für das Anlegen von Transportaufträgen, den Wechsel auf den AB „Transport Management“, das Erzeugen von ToCs oder die Freigabe von Transportaufträgen ist definitiv zu lang.

Wir alle wissen ja spätestens seit Einführung der Downgrade Protection (DGP), dass SAP SE gar nicht oder nur unter unrealistischen Laborbedingungen testet. Also hat auch hier SAP SE höchstens zwei bis drei kritische Objekte definiert und war dann mit der Performance sehr zufrieden.

Aber es muss doch da draußen auch Nutzer geben, die 10, 20, 100 oder sogar (wie wir) mehrere tausend kritische Objekte definieren?!

Zumal das Problem seit Einführung von Standard Changes im SAP Solution Manager 7.2 SP5 noch größer geworden ist, schließlich werden viele Anwender diese Änderungsart inklusive Whitelist-Feature nutzen wollen. Aber wenn da die Performance genauso ist, sehe ich schwarz.

Die schlechte Nachricht: SAP HANA hilft hier nicht viel. Das ist einfach nur richtig schlechte Programmierung.

Die gute Nachricht: Das Problem ist durch lokale Optimierungen lösbar:

Es kann so einfach sein.

Funktionsbaustein /TMWFLOW/RCK_CHECK_SM_CALL wird für die Durchführung der Prüfungen genutzt. Allerdings wird er viel zu häufig (einmal pro Transport, einmal pro Aufgabe, einmal pro ToC) aufgerufen. Eine Pufferung (ca. 60 Sekunden Gültigkeit des Puffers, implementiert mittels Enhancement-Technik) wirkt hier wunder.

Funktionsbaustein /TMWFLOW/BCO_READ_OBJECTS wird für das Lesen der Objektdefinitionen genutzt. Mittels Modifikation können folgende Optimierungen durchgeführt werden, die die Performance signifikant verbessern:

  • Die Nutzung sortierter interner Tabellen verhindert Full Table Scan.
  • Die Optimierung des SQL-Statements zum Lesen der ausschließlich benötigten Datensätze verhindert das prozessieren aller Datensätze.
  • Das Entfernen des Sortieren-Befehls aus der Loop-Schleife löste die Bremse.

Funktionsbaustein /TMWFLOW/BCO_CHECK_OBJECTS dient zur Durchführung der Objektprüfung durch Vergleich der Liste der kritischen Objekte mit dem Inhalt des zu prüfenden Transportauftrages. Sobald ein Objekt als kritisch identifiziert wird, wird es aus der Liste des Transportauftrageinhaltes in die Liste der kritischen Objekte verschoben. Diese Verschiebung kostet Zeit/Performance. Zudem ist diese Verschiebung u.U. gar nicht gewollt, da ein Objekt ggf. zu mehreren kritischen Objektdefinitionen passen kann und dann auch mehrfach angemahnt (und genehmigt) werden sollte. Folglich sollten alle Löschoperationen auf den internen Tabellen lt_bao6163 und lt_e071k per Modifikation entfernt werden. Außerdem sollten auch hier sortierte interne Tabellen genutzt werden und sofern möglich auf den Vergleichsoperator „contains pattern“ verzichtet werden.

Funktionsbaustein /TMWFLOW/RCK_APPLY_SPECS wird genutzt um die Liste der kritischen Objekte mit den bereits genehmigten kritischen Objekten abzumischen. Hier sollten ebenfalls sortierte interne Tabellen genutzt werden um performanceoptimal zu arbeiten. Zudem ist hier eine Fehlerkorrektur erforderlich, um zu verhindern, dass Genehmigung nicht wieder verloren gehen und um sicherzustellen, dass jede Objekt- oder Subobjektgenehmigung für nur genau dieses Objekt/Subobjekt angewendet wird.

Hier die entsprechendes Code-Snipsel:

FUNCTION /tmwflow/bco_read_objects.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_SPEC_NO) TYPE  /TMWFLOW/BCO_SPEC_NO OPTIONAL
*"  EXPORTING
*"     REFERENCE(ES_BCOOBJS_SPEC_NO) TYPE  /TMWFLOW/VBCOCRI
*"     REFERENCE(EV_NO_OBJECTS_DEFINED) TYPE  FLAG
*"  TABLES
*"      ET_BCOOBJS_TOTAL STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"      ET_BCOOBJS_OBJ STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"      ET_BCOOBJS_KEY STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"----------------------------------------------------------------------

*{   REPLACE        
*\  DATA: lt_bcoobjs      TYPE TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY,
*\        lt_bcoobjs_tmp  TYPE TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY.
  DATA: lt_bcoobjs      TYPE SORTED TABLE OF /tmwflow/vbcocri WITH UNIQUE KEY SPEC_NO LANGU,
        lt_bcoobjs_tmp  TYPE SORTED TABLE OF /tmwflow/vbcocri WITH UNIQUE KEY SPEC_NO LANGU.
*}   REPLACE
  DATA: ls_bcoobjs      TYPE          /tmwflow/vbcocri.

  FIELD-SYMBOLS:    LIKE LINE OF lt_bcoobjs_tmp.

  IF NOT iv_spec_no IS INITIAL.

    SELECT SINGLE * FROM /tmwflow/vbcocri INTO es_bcoobjs_spec_no
      WHERE spec_no EQ iv_spec_no
      AND   langu   EQ sy-langu.
    IF sy-subrc <> 0.

      SELECT SINGLE * FROM /tmwflow/vbcocri INTO es_bcoobjs_spec_no
        WHERE spec_no EQ iv_spec_no.
      IF es_bcoobjs_spec_no IS INITIAL.

        ev_no_objects_defined = 'X'.

      ENDIF.

    ENDIF.

  ELSE.

    REFRESH lt_bcoobjs_tmp.
    REFRESH lt_bcoobjs.

    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs
      WHERE langu EQ sy-langu.

*{   REPLACE        
*\    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs_tmp.
    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs_tmp where spec_no not in ( select spec_no from /tmwflow/vbcocri where langu EQ sy-langu ).
*}   REPLACE

    IF NOT lt_bcoobjs[] IS INITIAL.

      LOOP AT lt_bcoobjs_tmp ASSIGNING .

*{   DELETE         
*\        READ TABLE lt_bcoobjs WITH KEY spec_no = -spec_no TRANSPORTING NO FIELDS.
*\        IF sy-subrc <> 0.
*}   DELETE
*{   REPLACE        
*\          APPEND  TO lt_bcoobjs.
          INSERT  INTO TABLE lt_bcoobjs.
*}   REPLACE
*{   DELETE         
*\        ENDIF.
*}   DELETE

      ENDLOOP.

    ELSE.

      lt_bcoobjs[] = lt_bcoobjs_tmp[].

    ENDIF.

    IF NOT lt_bcoobjs[] IS INITIAL.

*{   DELETE         
*\      SORT lt_bcoobjs BY spec_no.
*}   DELETE
      DELETE ADJACENT DUPLICATES FROM lt_bcoobjs COMPARING spec_no.

      MOVE lt_bcoobjs[] TO et_bcoobjs_total[].

      LOOP AT lt_bcoobjs INTO ls_bcoobjs
        WHERE pgmid_obj  NE space
        AND   object_obj NE space
        AND   obj_name   NE space.

*{   REPLACE        
*\        APPEND ls_bcoobjs TO et_bcoobjs_obj.
*\        SORT et_bcoobjs_obj BY spec_no.
        INSERT ls_bcoobjs INTO TABLE et_bcoobjs_obj.
*}   REPLACE

      ENDLOOP.
      CLEAR ls_bcoobjs.
      LOOP AT lt_bcoobjs INTO ls_bcoobjs
        WHERE mastertype NE space
        AND   mastername NE space.

*{   REPLACE        
*\        APPEND ls_bcoobjs TO et_bcoobjs_key.
*\        SORT et_bcoobjs_key BY spec_no.
        INSERT ls_bcoobjs INTO TABLE et_bcoobjs_key.
*}   REPLACE

      ENDLOOP.

    ELSE.

      ev_no_objects_defined = 'X'.

    ENDIF.
  ENDIF.


ENDFUNCTION.
FUNCTION /tmwflow/rck_check_sm_call.
BEGINENHANCEMENT.

*SAP standard is calling this function module several times during one round trip.
*Since result will only change in case of changing transport request content or changing critical object definition we can assume that check is stable within a short time period.
*To improve performance we check critical objects only once per minute.

    TYPES:
    BEGIN OF ts_buffer,
      IS_trordhc         TYPE /TMWFLOW/TRORDHC,
      IV_sysname         TYPE /TMWFLOW/SYSNAME,
      IV_client          TYPE CTSCLIENT,
      EV_ABORT_EXPORT    TYPE FLAG,
      EV_CRITICAL_OBJECT TYPE FLAG,
      CT_MONI_LOG_ENTRY  TYPE STANDARD TABLE OF BALMI WITH DEFAULT KEY,
      ET_CRITICAL        TYPE STANDARD TABLE OF /TMWFLOW/VRCKAPP WITH DEFAULT KEY,
      timestamp          TYPE timestamp,
    END OF ts_buffer,
    tt_buffer TYPE SORTED TABLE OF ts_buffer WITH UNIQUE KEY IS_trordhc iv_sysname iv_client.

    STATICS:
    ss_buffer TYPE ts_buffer,
    st_buffer TYPE tt_buffer.

    DATA:
      lv_timestamp TYPE TZNTSTMPL,
      lv_date      TYPE sy-datum,
      lv_time      TYPE sy-uzeit.

*Get validty time.
    GET TIME STAMP FIELD lv_timestamp.
    lv_timestamp = CL_ABAP_TSTMP=>SUBTRACTSECS( TSTMP = lv_timestamp secs = 60 ).
    CONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC   ' INTO DATE lv_date TIME lv_time.
*   CONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time.

*Try to find entry in line buffer.
    IF ss_buffer-is_trordhc = is_trordhc AND ss_buffer-iv_sysname = iv_sysname AND ss_buffer-iv_client = iv_client.

      sy-subrc = 0.

    ELSE.

*Try to find entry in table buffer.
      READ TABLE st_buffer
      INTO ss_buffer
      WITH KEY is_trordhc = is_trordhc iv_sysname = iv_sysname iv_client = iv_client.

    ENDIF.

*Check whether found entry is still valid.
    IF sy-subrc = 0 AND ss_buffer-timestamp >= lv_timestamp.

*Check whether approval was changed since buffer entry creation.
      SELECT SINGLE APPR_TIME
      INTO lv_time
      FROM /tmwflow/rckwork
      WHERE trkorr = is_trordhc-trorder_number AND
            ( APPR_DATE > lv_date OR ( APPR_DATE = lv_date AND APPR_TIME > lv_time ) ).

      IF sy-subrc = 0.

*If it was changed: Forget buffer.
        DELETE TABLE st_buffer FROM ss_buffer.

      ELSE.

*Take result from buffer.
        MOVE:
        ss_buffer-ev_abort_export    TO EV_ABORT_EXPORT,
        ss_buffer-EV_CRITICAL_OBJECT TO EV_CRITICAL_OBJECT,
        ss_buffer-ET_CRITICAL        TO ET_CRITICAL[].

        APPEND LINES OF ss_buffer-CT_MONI_LOG_ENTRY TO CT_MONI_LOG_ENTRY.

        EXIT.

      ENDIF.

    ENDIF.

*Build new buffer entry.
    CLEAR ss_buffer.
    MOVE:
      IS_TRORDHC          TO ss_buffer-IS_TRORDHC,
      IV_SYSNAME          TO ss_buffer-IV_SYSNAME,
      IV_CLIENT           TO ss_buffer-IV_CLIENT,
      CT_MONI_LOG_ENTRY[] TO ss_buffer-CT_MONI_LOG_ENTRY.
*     lv_timestamp        to ss_buffer-timestamp.

    DO 1 TIMES.

ENDENHANCEMENT.

...
Two modifications here:
lt_bcobjt is a sorted table now to improve speed.
"CHECK et_critical IS SUPPLIED" is removed to ensure it will always be calculated.
...

BEGINENHANCEMENT.

    ENDDO.

*Get current timestamp.
    GET TIME STAMP FIELD lv_timestamp.

*Complete buffer entry.
    MOVE:
      lv_timestamp           TO ss_buffer-timestamp,
      EV_ABORT_EXPORT        TO ss_buffer-EV_ABORT_EXPORT,
      EV_CRITICAL_OBJECT     TO ss_buffer-EV_CRITICAL_OBJECT,
      ET_CRITICAL[]          TO ss_buffer-ET_CRITICAL.

    DATA:
      LT_MONI_LOG_ENTRY LIKE CT_MONI_LOG_ENTRY[].

    APPEND LINES OF CT_MONI_LOG_ENTRY FROM LINES( ss_buffer-CT_MONI_LOG_ENTRY ) + 1 TO LINES( CT_MONI_LOG_ENTRY ) TO LT_MONI_LOG_ENTRY.
    MOVE LT_MONI_LOG_ENTRY TO ss_buffer-CT_MONI_LOG_ENTRY.

*Store buffer entry in table buffer and keep it in line buffer.
    MODIFY TABLE st_buffer FROM ss_buffer.
    IF sy-subrc <> 0.
      INSERT ss_buffer INTO TABLE st_buffer.
    ENDIF.

ENDENHANCEMENT.
ENDFUNCTION.
FUNCTION /tmwflow/bco_check_objects.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_SYSNAME) TYPE  /TMWFLOW/SYSNAME
*"     REFERENCE(IV_CLIENT) TYPE  CTSCLIENT
*"     REFERENCE(IV_TRKORR) TYPE  TRKORR
*"     REFERENCE(IV_VERSION) TYPE  SYSAPRL
*"  EXPORTING
*"     REFERENCE(ET_MESSAGE) TYPE  BAPIRETTAB
*"  TABLES
*"      IT_BAO6163 STRUCTURE  BAO6163
*"      IT_E071K STRUCTURE  SCWB_E071K
*"      ET_CRITICAL STRUCTURE  /TMWFLOW/RCKWORK
*"----------------------------------------------------------------------

  DATA: lv_id                  TYPE /tmwflow/rckwork-id VALUE 0.
  DATA: lv_msg_txt             TYPE bapi_msg.
  DATA: ls_critical_export     TYPE /tmwflow/rckwork.
*{   REPLACE        
*\  DATA: lt_bao6163             TYPE STANDARD TABLE OF bao6163 WITH DEFAULT KEY.
  DATA: lt_bao6163             TYPE SORTED TABLE OF bao6163 WITH NON-UNIQUE KEY pgmid object obj_name WITH NON-UNIQUE SORTED KEY fragment components fragid fragment fragname.
*}   REPLACE
*{   REPLACE        
*\  DATA: lt_e071k               TYPE STANDARD TABLE OF scwb_e071k WITH DEFAULT KEY.
  DATA: lt_e071k               TYPE SORTED TABLE OF scwb_e071k WITH NON-UNIQUE KEY pgmid object objname.
*}   REPLACE
  DATA: lt_defined_critical    TYPE STANDARD TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY.
  DATA: lt_critical_export     TYPE STANDARD TABLE OF /tmwflow/rckwork WITH DEFAULT KEY.

  FIELD-SYMBOLS:
              LIKE LINE OF lt_defined_critical,
               LIKE LINE OF lt_bao6163,
            LIKE LINE OF lt_e071k.

  CLEAR et_critical.

  MOVE it_bao6163[] TO lt_bao6163[].
  MOVE it_e071k[]   TO lt_e071k[].

*--------------------------------------------------------------------*
* Get defined critical object in /TMWFLOW/COMSCONF

  CALL FUNCTION '/TMWFLOW/BCO_SPECIFICATIONS'
    EXPORTING
      iv_sys_name = iv_sysname
      iv_client   = iv_client
    TABLES
      et_critical = lt_defined_critical.
  CHECK lt_defined_critical IS NOT INITIAL.


*--------------------------------------------------------------------*
* Check for Workbench object

  LOOP AT lt_defined_critical ASSIGNING 
    WHERE pgmid_obj  <> space
      AND object_obj <> space.

    IF iv_version >= '2.00'.
      CHECK -pgmid_obj = gc_limu
        OR -pgmid_obj = gc_r3tr.
    ENDIF.

*{   INSERT         

*We can improve performance if we are not using patterns.
    IF -obj_name NA '*+'.

      DATA: lv_obj_name LIKE -obj_name.
      lv_obj_name = -obj_name.

      LOOP AT lt_bao6163 ASSIGNING  USING KEY primary_key
            WHERE ( ( pgmid    =  -pgmid_obj
                  AND object   =  -object_obj
                  AND obj_name =  lv_obj_name ) ).

        ls_critical_export-cid         = gc_check_bco.
        ls_critical_export-appr_status = gcs_object_status-critical.
        ls_critical_export-spec_no     = -spec_no.

        ls_critical_export-trkorr      = -trkorr.
        ls_critical_export-fragid      = -fragid.
        ls_critical_export-fragment    = -fragment.
        ls_critical_export-fragname    = -fragname.
        ls_critical_export-pgmid_obj   = -pgmid.
        ls_critical_export-object_obj  = -object.
        ls_critical_export-obj_name    = -obj_name.
        APPEND ls_critical_export TO lt_critical_export.

*\      DELETE lt_bao6163.

      ENDLOOP.

      DATA: lv_fragname LIKE -fragname.
      lv_fragname = -obj_name.

      LOOP AT lt_bao6163 ASSIGNING  USING KEY fragment
            WHERE ( ( fragid   =  -pgmid_obj
                  AND fragment =  -object_obj
                  AND fragname =  lv_fragname ) ).

        ls_critical_export-cid         = gc_check_bco.
        ls_critical_export-appr_status = gcs_object_status-critical.
        ls_critical_export-spec_no     = -spec_no.

        ls_critical_export-trkorr      = -trkorr.
        ls_critical_export-fragid      = -fragid.
        ls_critical_export-fragment    = -fragment.
        ls_critical_export-fragname    = -fragname.
        ls_critical_export-pgmid_obj   = -pgmid.
        ls_critical_export-object_obj  = -object.
        ls_critical_export-obj_name    = -obj_name.
        APPEND ls_critical_export TO lt_critical_export.

*\      DELETE lt_bao6163.

      ENDLOOP.

      CONTINUE.

    ENDIF.

*}   INSERT

    "!!!If subobject (belongs to defined critical object) is changed
    "we also take is as an additional cirtical object
    LOOP AT lt_bao6163 ASSIGNING 
       WHERE ( ( pgmid    =  -pgmid_obj
             AND object   =  -object_obj
             AND obj_name CP -obj_name )
       OR
               ( fragid   =  -pgmid_obj
             AND fragment =  -object_obj
             AND fragname CP -obj_name ) ).

      ls_critical_export-cid         = gc_check_bco.
      ls_critical_export-appr_status = gcs_object_status-critical.
      ls_critical_export-spec_no     = -spec_no.

      ls_critical_export-trkorr      = -trkorr.
      ls_critical_export-fragid      = -fragid.
      ls_critical_export-fragment    = -fragment.
      ls_critical_export-fragname    = -fragname.
      ls_critical_export-pgmid_obj   = -pgmid.
      ls_critical_export-object_obj  = -object.
      ls_critical_export-obj_name    = -obj_name.
      APPEND ls_critical_export TO lt_critical_export.

*{   DELETE         
*\      DELETE lt_bao6163.
*}   DELETE

    ENDLOOP.

  ENDLOOP.


*--------------------------------------------------------------------*
* Check for Customizing object

  CLEAR ls_critical_export.

  LOOP AT lt_defined_critical ASSIGNING 
    WHERE mastertype <> space
      AND mastername <> space.

*{   INSERT         
    IF  NOT -pgmid_key  = space "R3TR
    AND NOT -object_key = space "TABU
    AND NOT -objname    = space "Tablename without * and +
    AND NOT -objname CA '*+'
    AND NOT -mastertype = space "CDAT, VDAT, TABU
    AND NOT -mastername = space. "Clustername, Viewname or Tablename

*Filter 1
      LOOP AT lt_e071k ASSIGNING  USING KEY primary_key
            WHERE pgmid       =  -pgmid_key
            AND   object      =  -object_key
            AND   objname     =  -objname
            AND   mastertype  =  -mastertype.

*Filter 2
        CHECK ( -viewname   IS INITIAL OR -viewname   CP -viewname ) AND
              ( -mastername IS INITIAL OR -mastername CP -mastername ) AND
              ( -tabkey     IS INITIAL OR -tabkey     CP -tabkey ).

        MOVE-CORRESPONDING  TO ls_critical_export.

        ls_critical_export-cid            = gc_check_bco.
        ls_critical_export-appr_status    = gcs_object_status-critical.
        ls_critical_export-spec_no        = -spec_no.
        ls_critical_export-pgmid_key      = -pgmid_key.
        ls_critical_export-object_key     = -object_key.

        APPEND ls_critical_export TO lt_critical_export.

*        DELETE lt_e071k.

      ENDLOOP.

      CONTINUE.

    ENDIF.

*}   INSERT
    "the critical object could be table or view, that means, not both are empty is ok
    IF  NOT -pgmid_key  = space
    AND NOT -object_key = space
    AND NOT ( -objname = space
      AND -viewname   = space )
    AND NOT -mastertype = space
    AND NOT -mastername = space
    AND NOT -tabkey     = space.

      LOOP AT lt_e071k ASSIGNING 
          WHERE pgmid       =  -pgmid_key
          AND   object      =  -object_key
          AND ( objname     =  -objname
          OR    viewname    =  -viewname )
          AND   mastertype  =  -mastertype
*{   REPLACE        
*\          AND   mastername  =  -mastername
          AND   mastername  CP -mastername
*}   REPLACE
          AND   tabkey      CP -tabkey.

        MOVE-CORRESPONDING  TO ls_critical_export.

        ls_critical_export-cid            = gc_check_bco.
        ls_critical_export-appr_status    = gcs_object_status-critical.
        ls_critical_export-spec_no        = -spec_no.
        ls_critical_export-pgmid_key      = -pgmid_key.
        ls_critical_export-object_key     = -object_key.

        APPEND ls_critical_export TO lt_critical_export.

*{   DELETE         
*\        DELETE lt_e071k.
*}   DELETE

      ENDLOOP.

...

ENDFUNCTION.
FUNCTION /tmwflow/rck_apply_specs.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_CID) TYPE  /TMWFLOW/RCK_CID
*"     REFERENCE(IV_TRKORR) TYPE  SCWB_E070-TRKORR
*"     REFERENCE(IV_VERSION) TYPE  SYSAPRL
*"     REFERENCE(IV_SYS_NAME) TYPE  /TMWFLOW/SYSNAME OPTIONAL
*"     REFERENCE(IV_CLIENT) TYPE  /TMWFLOW/CLIENT OPTIONAL
*"  EXPORTING
*"     REFERENCE(ET_MESSAGE) TYPE  BAPIRETTAB
*"  TABLES
*"      TT_BAO6163 STRUCTURE  BAO6163
*"      TT_E071K STRUCTURE  SCWB_E071K
*"----------------------------------------------------------------------

  DATA: lv_flag               TYPE flag.
  DATA: lv_critical_objs      TYPE flag.
  DATA: lv_critical_keys      TYPE flag.
  DATA: ls_request_bao6163    LIKE bao6163.
  DATA: ls_request_scwb_e071k LIKE scwb_e071k.
  DATA: ls_approved_objects   TYPE /tmwflow/rckwork.
*{   REPLACE        
*\  DATA: lt_export_bao6163     TYPE STANDARD TABLE OF bao6163 WITH DEFAULT KEY.
*\  DATA: lt_export_scwb_e071k  TYPE STANDARD TABLE OF scwb_e071k WITH DEFAULT KEY.
  DATA: lt_export_bao6163     TYPE SORTED TABLE OF bao6163 WITH NON-UNIQUE KEY pgmid object obj_name fragid fragment fragname.
  DATA: lt_export_scwb_e071k  TYPE SORTED TABLE OF scwb_e071k WITH NON-UNIQUE KEY pgmid object objname mastertype mastername viewname tabkey.
*}   REPLACE
  DATA: lt_approved_objects   TYPE STANDARD TABLE OF /tmwflow/rckwork.
  DATA: lt_message            TYPE bapirettab.
  DATA: lv_msg_txt            TYPE bapi_msg.

  MOVE tt_bao6163[] TO lt_export_bao6163[].
  MOVE tt_e071k[]   TO lt_export_scwb_e071k[].

*--------------------------------------------------------------------*
* Exclude already approved Critical Objects

  SELECT * FROM /tmwflow/rckwork INTO TABLE lt_approved_objects
    WHERE trkorr        = iv_trkorr
    AND   cid           <> gc_check_mod
    AND   appr_status   = /tmwflow/cl_transport=>c_crit_obj_approved
    AND   appr_user     <> space
    AND   appr_date     <> space
    AND   appr_time     <> space.

  LOOP AT lt_approved_objects INTO ls_approved_objects.
    IF ls_approved_objects-sys_name <> iv_sys_name
      AND ls_approved_objects-client_id <> iv_client.
      CONTINUE.
    ENDIF.


    "Fix IM 1121109 2013 and 1131195 2013 for wrong handling of sub-object
    "Sub-object has own PGMID/OBJECT definition in /TMWFLOW/CMSCONF
    "so we only count it if the PGMID/OBJECT is fully matching
    "refer to function /TMWFLOW/BCO_CHECK_OBJECTS as how it's calculated
*{   INSERT         
      DATA: lv_obj_name LIKE ls_request_bao6163-obj_name.
      lv_obj_name = ls_approved_objects-obj_name.
*}   INSERT
    LOOP AT lt_export_bao6163 INTO ls_request_bao6163
*{   REPLACE        
*\      WHERE pgmid  =  ls_approved_objects-pgmid_obj
*\        AND object =  ls_approved_objects-object_obj.
      WHERE pgmid    = ls_approved_objects-pgmid_obj
        AND object   = ls_approved_objects-object_obj
        AND obj_name = lv_obj_name
        AND fragid   = ls_approved_objects-fragid
        AND fragment = ls_approved_objects-fragment
        AND fragname = ls_approved_objects-fragname.
*}   REPLACE
*     OR  ( fragid   =  ls_approved_objects-fragid
*     AND   fragment =  ls_approved_objects-fragment
*     AND   fragname =  ls_approved_objects-fragname ) ).

*{   DELETE         
*\    "This check is only for workbench critical objects
*\    CHECK ls_approved_objects-object_obj <> space OR ls_approved_objects-fragment IS NOT INITIAL.
*\      IF iv_version >= '2.00'.
*\        "Begin of Change for Novartis by Sawyer 2014/11/25 Incident 691666 2014
*\        IF ls_approved_objects-fragment = 'PMKC' OR
*\           ls_approved_objects-fragment = 'ACGR'.
*\          "Just continue
*\        ELSE.
*\          CHECK ls_approved_objects-pgmid_obj = gc_limu
*\            OR ls_approved_objects-pgmid_obj  = gc_r3tr.
*\        ENDIF.
*\        "End of Change for Novartis by Sawyer 2014/11/25
*\
*\        CHECK ls_request_bao6163-obj_name CP ls_approved_objects-obj_name.
*\      ELSE.
*\        CHECK ls_request_bao6163-obj_name = ls_approved_objects-obj_name.
*\      ENDIF.
*}   DELETE

      MESSAGE s120(/tmwflow/crit_obj)
        WITH ls_request_bao6163-trkorr
             ls_request_bao6163-object
             ls_request_bao6163-obj_name
             ls_approved_objects-appr_user INTO lv_msg_txt.

      message_set sy-msgty sy-msgid sy-msgno lv_msg_txt
                  sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
                  lt_message.
      APPEND LINES OF lt_message TO et_message.
      REFRESH lt_message.

      DELETE lt_export_bao6163.
      lv_flag = abap_true.
      lv_critical_objs = abap_true.

    ENDLOOP.


    LOOP AT lt_export_scwb_e071k INTO ls_request_scwb_e071k
        WHERE pgmid       =  ls_approved_objects-pgmid_key
        AND   object      =  ls_approved_objects-object_key
        AND   objname     =  ls_approved_objects-objname
        AND   mastertype  =  ls_approved_objects-mastertype
        AND   mastername  =  ls_approved_objects-mastername
        AND   viewname    =  ls_approved_objects-viewname
        AND   tabkey      =  ls_approved_objects-tabkey.

      MESSAGE s120(/tmwflow/crit_obj)
        WITH ls_request_scwb_e071k-trkorr
             ls_request_scwb_e071k-mastertype
             ls_request_scwb_e071k-mastername
             ls_approved_objects-appr_user
      INTO lv_msg_txt.
      message_set sy-msgty sy-msgid sy-msgno lv_msg_txt
                  sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
                  lt_message.
      APPEND LINES OF lt_message TO et_message.
      REFRESH lt_message.

      DELETE lt_export_scwb_e071k.
      lv_flag = abap_true.
      lv_critical_keys = abap_true.

    ENDLOOP.

    IF lv_flag <> abap_true.
      DELETE FROM /tmwflow/rckwork
        WHERE trkorr = ls_approved_objects-trkorr
        AND   id     = ls_approved_objects-id.

*{   DELETE         
*\      COMMIT WORK.
*}   DELETE
    ENDIF.

  ENDLOOP.
*{   INSERT         
     COMMIT WORK.
*}   INSERT


  IF lv_critical_objs = abap_true.
    REFRESH tt_bao6163.
    MOVE lt_export_bao6163[] TO tt_bao6163[].
  ENDIF.
  IF lv_critical_keys = abap_true.
    REFRESH tt_e071k.
    MOVE lt_export_scwb_e071k[] TO tt_e071k[].
  ENDIF.

ENDFUNCTION.

Die Prüfung eines Transportauftrages mit 40.000 Objekten gegen eine Objektliste mit 40.000 kritischen Objekten dauert jetzt ca. 20 Sekunden statt vorher mehr als 20 Minuten.