Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

ABAP query optimization

former_member693168
Participant
0 Likes
1,802

Hi to all.

I must optimize the following loop and query, it is making exactly what I need, but I need make it by the fastest way. How can I do it by the fastest way with maximum performance?

DATA wa_budat TYPE CHVW-BUDAT.

LOOP AT T_SHADOW ASSIGNING FIELD-SYMBOL(<FS_T_SHADOW>) WHERE MENGE IS NOT INITIAL.
  CLEAR wa_budat.

  SELECT SINGLE
    MAX( BUDAT )
  INTO wa_budat
  FROM
     CHVW
  WHERE
    WERKS = <FS_T_SHADOW>-WERKS
    AND MATNR = <FS_T_SHADOW>-MATNR
    AND CHARG = <FS_T_SHADOW>-CHARG
    AND
    (
      AUFNR = <FS_T_SHADOW>-AUFNR
      AND EBELN = <FS_T_SHADOW>-EBELN AND EBELP = <FS_T_SHADOW>-EBELP
      AND KDAUF = <FS_T_SHADOW>-KDAUF AND KDPOS = <FS_T_SHADOW>-KDPOS
      AND VBELN = <FS_T_SHADOW>-VBELN AND POSNR = <FS_T_SHADOW>-POSNR
    )
    AND XSTBW EQ abap_false.

  IF sy-subrc EQ 0.
    <FS_T_SHADOW>-ZZBUDAT = wa_budat.
  ENDIF.
ENDLOOP.
1 ACCEPTED SOLUTION
Read only

MateuszAdamus
Active Contributor
1,551

Hello mrrjesus

For one, you should try to provide a value for XZUGA field, as it's the first field of the primary key of the table. It will greatly increase the performance.

Other thing would be to provide a value for the AUFPS field, for the same reason as above.

Now, as to the implementation, you could do as Sandra proposed (temporary table or AMDP procedure). You can also try to do it in plain ABAP like shown below.

DATA(lt_shadow) = t_shadow[].
DELETE lt_shadow WHERE menge IS INITIAL.

SELECT werks, matnr, charg, aufnr, ebeln, ebelp, kdauf, kdpos, vbeln, posnr, budat
  FROM chvw
  FOR ALL ENTRIES IN @lt_shadow
  WHERE WERKS = @lt_shadow-werks
    AND MATNR = @lt_shadow-matnr
    AND CHARG = @lt_shadow-charg
    AND AUFNR = @lt_shadow-aufnr " brackets not needed for AND
    AND EBELN = @lt_shadow-ebeln 
    AND EBELP = @lt_shadow-ebelp
    AND KDAUF = @lt_shadow-kdauf 
    AND KDPOS = @lt_shadow-kdpos
    AND VBELN = @lt_shadow-vbeln 
    AND POSNR = @lt_shadow-posnr
    AND XSTBW = @abap_false
  INTO TABLE @lt_chvw.

SORT lt_chvw BY werks matnr charg aufnr ebeln ebelp kdauf kdpos vbeln posnr budat DESCENDING.

LOOP AT t_shadow REFERENCE INTO DATA(ld_shadow)
  WHERE menge IS NOT INITIAL.

  READ TABLE lt_chvw REFERENCE INTO DATA(ld_chvw)
    BINARY SEARCH
    WITH KEY werks = ld_shadow->werks
             matnr = ld_shadow->matnr
             charg = ld_shadow->charg
             aufnr = ld_shadow->aufnr
             ebeln = ld_shadow->ebeln
             ebelp = ld_shadow->ebelp
             kdauf = ld_shadow->kdauf
             kdpos = ld_shadow->kdpos
             vbeln = ld_shadow->vbeln
             posnr = ld_shadow->posnr.
  CHECK sy-subrc = 0.
  ld_shadow->zzbudat = ld_chvw->budat.
ENDLOOP.

Kind regards,

Mateusz
5 REPLIES 5
Read only

lumirion
Participant
1,551

Try not to SELECT within LOOP. Select all relevant data before looping with SELECT FOR ALL ENTRIES.

Read only

0 Likes
1,551

Thank you. Your strategy is what I need.

Read only

Sandra_Rossi
Active Contributor
0 Likes
1,551

Don't forget to do performance tests before and after change.

Of course, SELECT inside a loop is prohibited as a rule-of-thumb.

I see that you have MAX, so you can't use FOR ALL ENTRIES.

You may create a temporary database table to contain the internal table T_SHADOW, with columns WERKS, MATNR, CHARG, AUFNR, EBELN, etc.

With a Global Temporary Table (GTT), its content is deleted after COMMIT and concurrency is managed.

I think that you may also join directly with the internal table passed to a database procedure (AMDP/SQL Script).

All these possibilities depend on your ABAP version.

Read only

MateuszAdamus
Active Contributor
1,552

Hello mrrjesus

For one, you should try to provide a value for XZUGA field, as it's the first field of the primary key of the table. It will greatly increase the performance.

Other thing would be to provide a value for the AUFPS field, for the same reason as above.

Now, as to the implementation, you could do as Sandra proposed (temporary table or AMDP procedure). You can also try to do it in plain ABAP like shown below.

DATA(lt_shadow) = t_shadow[].
DELETE lt_shadow WHERE menge IS INITIAL.

SELECT werks, matnr, charg, aufnr, ebeln, ebelp, kdauf, kdpos, vbeln, posnr, budat
  FROM chvw
  FOR ALL ENTRIES IN @lt_shadow
  WHERE WERKS = @lt_shadow-werks
    AND MATNR = @lt_shadow-matnr
    AND CHARG = @lt_shadow-charg
    AND AUFNR = @lt_shadow-aufnr " brackets not needed for AND
    AND EBELN = @lt_shadow-ebeln 
    AND EBELP = @lt_shadow-ebelp
    AND KDAUF = @lt_shadow-kdauf 
    AND KDPOS = @lt_shadow-kdpos
    AND VBELN = @lt_shadow-vbeln 
    AND POSNR = @lt_shadow-posnr
    AND XSTBW = @abap_false
  INTO TABLE @lt_chvw.

SORT lt_chvw BY werks matnr charg aufnr ebeln ebelp kdauf kdpos vbeln posnr budat DESCENDING.

LOOP AT t_shadow REFERENCE INTO DATA(ld_shadow)
  WHERE menge IS NOT INITIAL.

  READ TABLE lt_chvw REFERENCE INTO DATA(ld_chvw)
    BINARY SEARCH
    WITH KEY werks = ld_shadow->werks
             matnr = ld_shadow->matnr
             charg = ld_shadow->charg
             aufnr = ld_shadow->aufnr
             ebeln = ld_shadow->ebeln
             ebelp = ld_shadow->ebelp
             kdauf = ld_shadow->kdauf
             kdpos = ld_shadow->kdpos
             vbeln = ld_shadow->vbeln
             posnr = ld_shadow->posnr.
  CHECK sy-subrc = 0.
  ld_shadow->zzbudat = ld_chvw->budat.
ENDLOOP.

Kind regards,

Mateusz
Read only

1,551

Perfect. Your answer is exactly what I need. You gave me a solution with a surgical precision.

Thank you so much. God bless you.