我有两部分代码。他们两个都处理了150万条记录,但第一部分需要20分钟而第二部分需要13.5小时!!!!!!
这是第一部分:
loop at it_bkpf.
select * from bseg into corresponding fields of itab
where bukrs = it_bkpf-bukrs and
belnr = it_bkpf-belnr and
gjahr = it_bkpf-gjahr and
hkont in s_hkont.
if sy-subrc = 0 .
itab-budat = it_bkpf-budat.
clear *bseg .
select single * from *bseg
where bukrs = itab-bukrs and
belnr = itab-belnr and
gjahr = itab-gjahr and
hkont = wtax .
if sy-subrc <> 0 .
itab-budat = '99991231'.
endif.
endif.
append itab.
endselect.
endloop.
第13小时的第2部分如下:
sort itab by belnr.
loop at itab where hkont(2) = '73'.
move-corresponding itab to itab2.
collect itab2.
endloop.
loop at itab2.
lv_5per_total = con_5per_tax * itab2-dmbtr.
lv_5per_upper = lv_5per_total + '0.02'.
lv_5per_lower = lv_5per_total - '0.02'.
read table itab with key belnr = itab2-belnr
hkont = wtax.
if sy-subrc = 0.
if itab-dmbtr between lv_5per_lower and lv_5per_upper.
itab-budat = '99991231'.
modify itab transporting budat where belnr = itab2-belnr.
endif.
endif.
endloop.
有没有人知道如何修理第二部分?
一些额外的东西:
it_bkpf有150万条记录
在第一个过程之后,ITAB拥有150万条记录
在第一个循环的第二部分中,我总结了以73开头的账户的每个belnr的金额
在第二个循环中,我将每个belnr的总和与belnr / account的数量进行比较,然后执行代码所说的内容。
感谢
其他信息:
所有初始代码中的第一个存在,我添加了新的代码。 ITAB存在,ITAB2是我的。所以表格的声明是:
DATA : BEGIN OF itab OCCURS 0,
bukrs LIKE bseg-bukrs,
hkont LIKE bseg-hkont,
belnr LIKE bkpf-belnr,
gjahr LIKE bkpf-gjahr,
dmbtr LIKE bseg-dmbtr,
shkzg LIKE bseg-shkzg ,
budat LIKE bkpf-budat,
zzcode LIKE bseg-zzcode.
DATA END OF itab.
DATA : BEGIN OF itab2 OCCURS 0 ,
belnr LIKE bkpf-belnr,
dmbtr LIKE bseg-dmbtr,
END OF itab2.
在您提出建议后,我做了以下更改:
types: begin of ty_belnr_sums,
belnr like bkpf-belnr,
dmbtr like bseg-dmbtr,
end of ty_belnr_sums.
data: git_belnr_sums type sorted table of ty_belnr_sums
with unique key belnr.
data: gwa_belnr_sums type ty_belnr_sums.
data: lv_5per_upper type p decimals 2,
lv_5per_lower type p decimals 2,
lv_5per_total type p decimals 2.
sort itab by belnr hkont.
loop at itab where hkont(2) = '73'.
move-corresponding itab to gwa_belnr_sums.
collect gwa_belnr_sums into git_belnr_sums .
endloop.
loop at git_belnr_sums into gwa_belnr_sums.
lv_5per_total = con_5per_tax * gwa_belnr_sums-dmbtr.
lv_5per_upper = lv_5per_total + '0.02'.
lv_5per_lower = lv_5per_total - '0.02'.
read table itab with key belnr = gwa_belnr_sums-belnr
hkont = wtax
binary search.
if sy-subrc = 0.
if itab-dmbtr between lv_5per_lower and lv_5per_upper.
itab-budat = '99991231'.
modify itab transporting budat
where belnr = gwa_belnr_sums-belnr.
endif.
endif.
endloop.
现在我在后台运行了150万条记录,并在1小时后继续运行。
答案 0 :(得分:0)
这里有几个性能问题:
第一部分:
永远不要在SELECT
中LOOP
。我永远不会说。您应该改为SELECT ... FOR ALL ENTRIES
或SELECT ... JOIN
(BSEG是ECC中的集群表,因此不可能有JOIN,但S4 / HANA中的透明表,因此您可以使用BKPF加入它)。据我从编码中看到,您选择G / L项目,因此您可以检查使用BSIS / BSAS是否会更好(而不是BSEG)。您还可以查看表BSET(看起来您对“税”行感兴趣)
第二部分:
如果您执行LOOP
WHERE
条件,如果内部表格为TYPE SORTED
(使用正确的密钥),则会获得最佳效果。但是,您的WHERE
条件使用偏移量,因此我不确定SORTED
表是否有用,但值得一试。
但真正的问题在于:COLLECT itab2
。 COLLECT
表不支持TYPE STANDARD
(这在SAPHelp中有明确说明),内部表必须是TYPE HASHED
(背后有技术原因,我不会详细介绍)
之后你LOOP
一个内部表(itab2)和READ TABLE另一个(itab)。为了获得单行读取的最佳性能,itab必须为TYPE HASHED
(或至少TYPE SORTED
使用正确的密钥。)
您不必使用带有HEADER LINES的内部表,而是LOOP ... ASSIGNING FIELD-SYMBOL(<...>)
,因此您不再需要MODIFY
,这也会略微提高性能。
答案 1 :(得分:0)
正如JozsefSzikszai所说,最好使用BSAS / BSIS,因为它们有索引。如果你真的想使用BSEG: BSEG是一个集群表。 AFAIK,这些表最好使用关键字段来执行SELECT以获取内部表,然后在内部表上处理其他字段
select * from bseg into corresponding fields of itab
for all entries in it_bkpf
where bukrs = it_bkpf-bukrs and
belnr = it_bkpf-belnr and
gjahr = it_bkpf-gjahr.
delete itab where hkont not in s_hkont.
在第二部分中,您将在标准表(itab)上执行READ TABLE。 使用BINARY搜索会在你的时间内切断极大 ...标准表上的读表是全表扫描(读取行直到找到值)。通过belnr和hkont(而不仅仅是belnr)和addinf BINARY SEARCH对itab进行排序将使其成为二分法搜索。
答案 2 :(得分:0)
我猜所有人都给了你优化代码的所有提示。基本上,由于您只想优化第二部分,唯一的问题似乎是itab
操作(循环,读取,修改),您可以通过在内部使用索引或哈希表来改进表itab。如果这些概念不清楚,我建议使用ABAP文档:Row-Based Administration Costs of Internal Tables和Internal Tables - Performance Notes
还有两件事:
现在,如果您接受在第1部分中调整一些小东西,在阅读每个文档的BSEG行之后,您可以简单地循环这些行,不需要索引或二进制搜索或哈希表,那已经完成了。唯一要做的就是首先将BSEG的行存储在一个临时itab_temp
中,一次只包含一个文档的行,这样你只能在这些行上循环,然后将它们添加到{{ 1}}。
如果您想稍后更新BUDAT组件,而不是第1部分,则将文档密钥+ BUDAT存储在不同的内部表(例如itab
)中,并定义非唯一的辅助使用文档关键字段(例如itab_budat
)在itab
上建立索引,您只需要这个直接的代码:
by_doc_key
请注意,我建议使用(非唯一)次要索引,而不是主要索引,因为您不想更改(太多)第1部分,这样可以避免潜在问题您可能拥有主索引。
如果您需要有关术语,语法等的更多信息,可以在ABAP文档(内联或Web)中找到它们。
答案 3 :(得分:0)
很多人提出了合理的建议,特别是来自桑德拉罗西,但我只是将我的两分钱加到你最新的1小时变种中:
DEMO_SECONDARY_KEYS
)INTO CORRESPONDING FIELDS
,这会慢慢减慢查询速度BUDAT
仅在BSEG
位置总和适合较低 - 较高范围时写入。因此,一些收集的款项正在浪费时间。总而言之,我还没有完全理解您的逻辑,因为您将BUDAT
写入整个匹配的行集,而仅写入匹配的组的第一行 BELNR
,没有任何意义,但仍然如此。
尽管如此,如果一个人尝试在没有任何改动的情况下重复逻辑并应用新的GROUP BY
语法,那么这就是人们可能得到的。
* To omit `INTO CORRESPONDING` you should properly declare your structure
* and fetch only those fields which are needed. Also avoid obsolete `OCCURS` syntax.
TYPES: BEGIN OF ty_itab,
bukrs TYPE bseg-bukrs,
belnr TYPE bkpf-belnr,
gjahr TYPE bkpf-gjahr,
hkont TYPE bseg-hkont,
dmbtr TYPE bseg-dmbtr,
shkzg TYPE bseg-shkzg ,
budat TYPE bkpf-budat,
END OF ty_itab.
TYPES: begin of ty_belnr_sums,
belnr type bkpf-belnr,
dmbtr type bseg-dmbtr,
end of ty_belnr_sums.
DATA: itab TYPE TABLE OF ty_itab INITIAL SIZE 0,
con_5per_tax type p decimals 2 value '0.03'.
SELECT g~bukrs g~belnr g~gjahr g~hkont g~dmbtr g~shkzg f~budat UP TO 1500000 rows
INTO table itab
FROM bseg AS g
JOIN bkpf AS f
ON g~bukrs = f~bukrs
AND g~belnr = f~belnr
AND g~gjahr = f~gjahr.
DATA members LIKE itab.
LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs_itab>)
GROUP BY ( belnr = <fs_itab>-belnr )
hkont = <fs_itab>-hkont )
ASCENDING
ASSIGNING FIELD-SYMBOL(<group>).
CLEAR members.
CHECK <group>-hkont(2) = '73'.
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<group_line>).
members = VALUE #( BASE members ( <group_line> ) ).
ENDLOOP.
DATA(sum) = REDUCE dmbtr( INIT val TYPE dmbtr
FOR wa IN members
NEXT val = val + wa-dmbtr ).
IF members[1]-dmbtr BETWEEN con_5per_tax * sum - '0.02' AND con_5per_tax * sum + '0.02'.
<first_line>-budat = '99991231'.
ENDIF.
ENDLOOP.
在我对1.5M数据集的测试期间,我使用GET RUN TIME FIELD
测量了运行时间并获得了以下结果。
旧片段:
我的片段: