Dazu hatte ich dann noch was geschrieben, und noch eine Ergänzung: jeder einzelne Partner kann alleine auf der Position vorkommen oder auch nicht. Die Variante, zuerst Kopfpartner durchzuackern und dann ggf. mit Positionspartnern zu überschreiben, ist bei diesen zwei loops die richtigere, bis auf das Problem mit den erwähnten select options.DeathAndPain hat geschrieben: ↑18.11.2019 13:48Wenn das durch die Prüfung auf POSNR IS INITIAL repräsentiert wird, dann könntest Du da auch nochmal optimieren und meinen Codevorschlag wie folgt umstellen:
Dann würdest Du Dir das Lesen des Kopfpartners sparen, wenn Du Positionspartner findest und hättest damit nochmals Performance rausgemolken.Code: Alles auswählen.
LOOP AT lt_vbpa ASSIGNING FIELD-SYMBOL(<lw_vbpa>) WHERE vbeln = lw_grid_tab-vbeln AND posnr = lw_grid_tab-posnr. PERFORM whatever_you_wanna_do USING <lw_vbpa>. ENDLOOP. IF sy-subrc <> 0. LOOP AT lt_vbpa ASSIGNING <lw_vbpa> WHERE vbeln = lw_grid_tab-vbeln AND posnr = '000000'. PERFORM whatever_you_wanna_do USING <lw_vbpa>. ENDLOOP. ENDIF.
Mein Daumen ist ausreichend genau - ich muss nicht alles ausprogrammieren. Und auch SAT wirft eine Gesamtzeit aus, wenn ich es auf ms genau wissen wollte.Du weißt aber, dass es ABAP-Befehle zur Laufzeitmessung gibt? Lies Dir mal die F1-Hilfe von GET RUN TIME durch.
@black_adeptblack_adept hat geschrieben: ↑18.11.2019 13:52@ M@atze: Den Austausch von INTO durch ASSIGNING hört man ja häufiger um ein Programm zu beschleunigen. (Und ich selber verwende deshalb fast ausschließlich ASSIGNING ).
Jedoch bringt das bei Programmen, die mit der Laufzeit zu kämpfen haben so gut wie gar nix.
Ich habe ein Testprogramm ( wenn das jemand haben möchte PM an mich ) und habe das mit diversen Konstellationen getestet:
Ja - das ASSIGN ist bei mir zwischen Faktor 1,5 und 5 schneller
ABER, bei z.b. 10 Millionen Zeilen über eine Tabelle mit 10 Felder der Breite 10: 0,5 Sekunden ( Faktor 1,8 ) oder bei 100000 Zeilen einer Tabelle mit 100 Feldern der Breite 100: 0,2 Sekunden ( Faktor 4 ). Das sind aber reine LOOPs, die gar nichts innerhalb des LOOPs machen. Normalerweise kommt die Laufzeit aber durch die Aktionen innerhalb des Loops und nicht durch die Art der Zuweisung
Bei meinem Test im Entwicklungssystem hab ich gut 10.000 Sätze aus dem initialen select, und wenn ich die VBPA vor dem loop lese, sind da gut 14000 Zeilen drin. Das Verhältnis wird im Produktivsystem ähnlich sein, da ist dann nur die Frage, wie groß sie selektieren. Und die Auswertung, die ich hier ablösen will, läuft immer wieder einmal in TSV_TNEW_PAGE_ALLOC_FAILED, weil die Anwender vergessen, ordentlich einzuschränken...
Noch einmal: die angeführten Mengen sind meine Testdaten. Da krieg ich gerade schon brauchbar messbare Laufzeiten, die ich auch erwähnt habe. Am Produktivsystem reden wir von ganz anderen Selektionen, wie beschrieben. De facto hab ich also ein Laufzeitthema.
was erwartest du denn als Laufzeit? Wenn dein Programm mit 14.000 Datensätzen 12 Sek. läuft, finde ich das durchaus in Ordnung...
Das kann ich bei diesem Beispiel NICHT bestätigen! Die Laufzeit später im Loop ist ähnlich; egal, ob ich nur das Notwendigste an Feldern verwende oder ob ich die gesamte VBAK, VBAP etc nutze!
Code: Alles auswählen.
REPORT.
PARAMETERS p_count TYPE i DEFAULT 10000.
TYPES: BEGIN OF ts_sales_data,
"key
vbeln TYPE vbeln,
posnr TYPE posnr,
"header
vbtyp TYPE vbtyp,
auart TYPE auart,
erdat TYPE sydatum,
ernam TYPE syuname,
"item
matnr TYPE matnr,
arktx TYPE arktx,
kwmeng TYPE kwmeng,
meins TYPE meins,
"partner
ag TYPE kunnr,
we TYPE kunnr,
rg TYPE kunnr,
re TYPE kunnr,
END OF ts_sales_data,
tt_sales_data TYPE SORTED TABLE OF ts_sales_data WITH UNIQUE KEY vbeln posnr.
TYPES: BEGIN OF my_vbak,
vbeln TYPE vbeln,
vbtyp TYPE vbtyp,
auart TYPE auart,
ernam TYPE syuname,
erdat TYPE sydatum,
END OF my_vbak,
BEGIN OF my_vbap,
vbeln TYPE vbeln,
posnr TYPE posnr,
vbtyp TYPE vbtyp,
matnr TYPE matnr,
arktx TYPE arktx,
kwmeng TYPE kwmeng,
meins TYPE meins,
END OF my_vbap,
BEGIN OF my_vbpa,
vbeln TYPE vbeln,
posnr TYPE posnr,
parvw TYPE parvw,
kunnr TYPE kunnr,
lifnr TYPE lifnr,
adrnr TYPE ad_addrnum,
END OF my_vbpa,
my_vbpa_t TYPE SORTED TABLE OF my_vbpa WITH UNIQUE KEY vbeln posnr parvw.
DATA sales_items TYPE SORTED TABLE OF my_vbap WITH UNIQUE KEY vbeln posnr.
DATA sales_orders TYPE SORTED TABLE OF my_vbak WITH UNIQUE KEY primary_key COMPONENTS vbeln.
DATA sales_partners TYPE SORTED TABLE OF my_vbpa WITH UNIQUE KEY vbeln posnr parvw.
*DATA sales_items TYPE SORTED TABLE OF vbap WITH UNIQUE KEY vbeln posnr.
*DATA sales_orders TYPE SORTED TABLE OF vbak WITH UNIQUE KEY primary_key COMPONENTS vbeln.
*DATA sales_partners TYPE SORTED TABLE OF vbpa WITH UNIQUE KEY vbeln posnr parvw.
DATA sales_data TYPE tt_sales_data.
START-OF-SELECTION.
PERFORM init.
GET RUN TIME FIELD DATA(start).
PERFORM loop.
GET RUN TIME FIELD DATA(stopp).
DATA(diff) = ( stopp - start ) / 1000.
WRITE: / 'Sales orders: ', lines( sales_orders ).
WRITE: / 'Sales items: ', lines( sales_items ).
WRITE: / 'Sales partners: ', lines( sales_partners ).
WRITE: / 'run time: ', diff, 'millisec'.
FORM loop.
DATA date TYPE ts_sales_data.
DATA data TYPE tt_sales_data.
LOOP AT sales_orders INTO DATA(order).
LOOP AT sales_items INTO DATA(item)
WHERE vbeln = order-vbeln.
date-vbeln = order-vbeln.
date-vbtyp = order-vbtyp.
date-auart = order-auart.
date-ernam = order-ernam.
date-erdat = order-erdat.
date-posnr = item-posnr.
date-matnr = item-matnr.
date-arktx = item-arktx.
date-kwmeng = item-kwmeng.
date-meins = item-meins.
LOOP AT sales_partners INTO DATA(partner_pos)
WHERE vbeln = item-vbeln
AND posnr = item-posnr.
date-ag = partner_pos-kunnr.
date-we = partner_pos-kunnr.
date-re = partner_pos-kunnr.
date-rg = partner_pos-kunnr.
ENDLOOP.
IF sy-subrc > 0.
LOOP AT sales_partners INTO DATA(partner_head)
WHERE vbeln = item-vbeln
AND posnr = '000000'.
date-ag = partner_head-kunnr.
date-we = partner_head-kunnr.
date-re = partner_head-kunnr.
date-rg = partner_head-kunnr.
ENDLOOP.
ENDIF.
INSERT date INTO TABLE data.
ENDLOOP.
ENDLOOP.
ENDFORM.
FORM init.
DATA sales_order_template TYPE my_vbak.
DATA sales_item_template TYPE my_vbap.
DATA(rnd) = cl_abap_random_int=>create(
seed = 18
min = 1
max = 50 ).
DATA(rnd_partner) = cl_abap_random_int=>create(
seed = 18
min = 1
max = 3 ).
SELECT * FROM vbak INTO CORRESPONDING FIELDS OF @sales_order_template UP TO 1 ROWS.
ENDSELECT.
SELECT * FROM vbap INTO CORRESPONDING FIELDS OF @sales_item_template UP TO 1 ROWS.
ENDSELECT.
DATA count_items TYPE i.
DO p_count TIMES.
sales_order_template-vbeln = |{ sy-index ALIGN = RIGHT WIDTH = 10 PAD = '0' }|.
INSERT sales_order_template INTO TABLE sales_orders.
INSERT LINES OF VALUE my_vbpa_t(
vbeln = sales_order_template-vbeln
( parvw = 'AG' kunnr = 'AGDUMMY' )
( parvw = 'WE' kunnr = 'WEDUMMY' )
( parvw = 'RE' kunnr = 'REDUMMY' )
( parvw = 'RG' kunnr = 'RGDUMMY' ) ) INTO TABLE sales_partners.
count_items = rnd->get_next( ).
DO count_items TIMES.
sales_item_template-vbeln = sales_order_template-vbeln.
sales_item_template-posnr = |{ sy-index * 10 ALIGN = RIGHT WIDTH = 6 PAD = '0' }|.
INSERT sales_item_template INTO TABLE sales_items.
IF rnd_partner->get_next( ) = 1.
INSERT LINES OF VALUE my_vbpa_t(
vbeln = sales_item_template-vbeln
posnr = sales_item_template-posnr
( parvw = 'AG' kunnr = 'AGDUMMYPOS' )
( parvw = 'WE' kunnr = 'WEDUMMYPOS' )
( parvw = 'RE' kunnr = 'REDUMMYPOS' )
( parvw = 'RG' kunnr = 'RGDUMMYPOS' ) ) INTO TABLE sales_partners.
ENDIF.
ENDDO.
ENDDO.
ENDFORM.