abap数据优化的几种方式
● 使用FOR ALL ENTRIES语句,在使用该语句之前,应判断内表是否为空.
IF gt_delivery IS NOT INITIAL.
SELECT DISTINCT
a~vbelv,
a~posnv,
a~vbeln,
a~posnv,
b~bstnk,
c~kdmat, "客户物料 Moof-200001
c~zzsto1,
c~kwmeng "add xjw-210412
INTO CORRESPONDING FIELDS OF TABLE @lt_vbap
FROM vbfa AS a
INNER JOIN vbak AS b ON b~vbeln = a~vbelv
INNER JOIN vbap AS c ON c~vbeln = a~vbelv
AND c~posnr = a~posnv
FOR ALL ENTRIES IN @gt_delivery
WHERE a~vbeln = @gt_delivery-vgbel
AND a~posnn = @gt_delivery-vgpos.
-
对于一些大表(例如MSEG、BSEG等)的查询,尽量带入主键或索引进行查
-
尽量避免使用SELECT * INTO CORRESPONDING语句以减少系统资源负载.
-
LOOP 循环中禁止使用SELECT语句,可用SELECT取出放到临时内表,在循环读表.
LOOP AT itab.
READ TABLE sub_itab WITH KEY vbeln = itab-vbeln.
itab-name1 = sub_itab-name1.
MODIFY itab.
CLEAR itab.
CLEAR sub_itab.
ENDLOOP.
● 在使用JOIN语句时应尽可能使用KEY保证条件唯一性。
● 尽量不要LOOP循环中嵌套循环.
● 单个FORM尽量不要超过200行
少使用select * 而是采用select 字段1 ,字段2 ,… 方式查询.
● loop里面,不要用sort和select ,更不要loop里面嵌套loop
对于多表查询,可以拆分表为多个表进行大表loop 小表read
*&---------------------------------------------------------------------*
*& Report ZPROGRAME_TEST_MORETABLE1
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zprograme_test_moretable1.
TABLES: vbap,vbep,vbak,kna1.
PARAMETERS p LIKE vbap-vbeln VALUE CHECK.
DATA: BEGIN OF itab OCCURS 0 ,
vbeln TYPE vbap-vbeln,
posnr TYPE vbap-posnr,
wmeng TYPE vbep-wmeng,
netwr TYPE vbap-netwr,
waerk TYPE vbap-waerk,
edatu TYPE vbep-edatu,
name1 TYPE kna1-name1,
name2 type kna1-name2,
END OF itab.
DATA: BEGIN OF sub_itab OCCURS 0,
vbeln LIKE vbak-vbeln,
name1 LIKE kna1-name1,
name2 LIKE kna1-name2,
END OF sub_itab.
***********************************************************************
* Event Start-of-selection
***********************************************************************
START-OF-SELECTION.
SELECT ap~vbeln ap~posnr ep~wmeng ap~netwr ap~waerk ep~edatu k~name1
INTO CORRESPONDING FIELDS OF TABLE itab
FROM vbap AS ap
INNER JOIN vbep AS ep ON ap~vbeln = ep~vbeln
AND ap~posnr = ep~posnr
INNER JOIN vbak AS ak ON ak~vbeln = ap~vbeln
INNER JOIN kna1 AS k ON k~kunnr = ak~kunnr
UP TO 30 ROWS WHERE ap~vbeln = p.
SKIP.ULINE.ULINE.
WRITE: '开始第一种查询法',/.
skip.
write:'销售凭证', '项目','订单数量','订单项目的凭证货币净值','销售和分销凭证货币','计划行日期','名称 1','名称 2', '第n行数据'.
LOOP AT itab.
WRITE: / itab-vbeln,
itab-posnr,
itab-wmeng,
itab-netwr,
itab-waerk,
itab-edatu,
itab-name1.
ENDLOOP.
**********************************************************
*demo2
*Event start-of-selection
*
**********************************************************
START-OF-SELECTION.
clear itab. clear sub_itab .
SELECT ap~vbeln ap~posnr ep~wmeng ap~netwr ap~waerk ep~edatu
INTO CORRESPONDING FIELDS OF TABLE itab
FROM vbap AS ap
INNER JOIN vbep AS ep ON ap~vbeln = ep~vbeln
AND ap~posnr = ep~posnr UP TO 30 ROWS WHERE ap~vbeln = p.
SELECT ak~vbeln k~name1 k~name2
INTO TABLE sub_itab
FROM vbak AS ak INNER JOIN kna1 AS k ON ak~kunnr = k~kunnr
FOR ALL ENTRIES IN itab WHERE ak~vbeln = itab-vbeln . " 000010 0.000 4.00 USD 2019/02/28 联想(北京)有限公司 - 东莞讯
LOOP AT itab.
READ TABLE sub_itab WITH KEY vbeln = itab-vbeln.
itab-name1 = sub_itab-name1.
MODIFY itab.
CLEAR itab.
CLEAR sub_itab.
ENDLOOP.
ULINE.
DATA: count TYPE int2 .
count = 0 .
WRITE: '开始第二种查询法',/.
skip.
write:'销售凭证', '项目','订单数量','订单项目的凭证货币净值','销售和分销凭证货币','计划行日期','名称 1','名称 2', '第n行数据'.
LOOP AT itab.
count = count + 1 .
WRITE: / itab-vbeln,
itab-posnr,
itab-wmeng,
itab-netwr,
itab-waerk,
itab-edatu,
itab-name1,
itab-name2,
count .
ENDLOOP.
● 尽量避免LOOP里面不用delete,append等语句。改成批量处理
● 使用正确的表。SAP有标准的索引表或者VIEW。参见sap notes 185530/191492/187906 LIPS 使用VGBEL不如先用VBFA表
● 使用正确的索引。好的索引非常好。不好的索引可能索引比表大,也有的索引让当前程序变快,其它的程序却变慢了。
新建索引转产以前都需要分析索引是否建的有效
● 多次存取数据库,不如一次存取批量的数据。尽量减少访问数据库的次数
● 对于MSEG,MKPF,LIPS等表,尽量少用inner join。根据有利的筛选字段过滤较小的数据集以后,在内表处理
● 多用for all entries,先做三步check:drive table是否为空;排序;去重(delete duplicate records)
● 对于in range table的搜索,超过一定数据量就会出现dump
● ST10分析那些是hot table,为这些表分配固定的缓存,提高缓存命中率,减少数据库访问次数。对于命中率低的表,单独建立较小的缓存区,防止覆盖hot table的缓存。DB02 分析哪些表的缓存效率好,哪些表的缓存效率低
● 策略:不必为小概率的错误牺牲大量数据处理的效率。批量保存时,采用异步保存可以大大提高效率。可以通过事后纠错来减少数据不一致的情况。
● 大数据的read table,使用二分法 BINARY SEARCH,用之前要按关键字排序
● index的使用,在使用现有的index的时候注意,where条件里面的字段的顺序要跟index一致,而且可以可以适当的去匹配index,创建一些空的字段或者是index后面再加字段,或者是使用index抓出数据后,再去做其它条件的处理。
● index里面最好只有’=’ AND 或者是‘IN’。有其它逻辑条件,会影响index的使用。
● 如果表是有buffer,可以考虑使用buffer,这样性能也可以有很好的提升,不过首先要去表看看这个是否有buffer:
SELECT SINGLE * FROM T100 INTO T100_WA
BYPASSING BUFFER
WHERE SPRSL = 'D'.
● 大部分表都有buffer,而且这个我们很难控制,但是我们写出来的语句要经可能的避免“不读buffer”:
● 一般程序到表抓数的时候,会在应用服务层有数据缓存,所以同一个程序,在不同时间先后跑,后面的通常会比较快,因为可以到数据缓存读书。
● NOT,只能全表扫描,不要用not,换成反面。建议between 换成IN。不建议使用LIKE OR
一 .使用一些简单的语句代替复杂的嵌套LOOP:
1、用批量处理的BAPI替换,LOOP 里面call BAPI,例如用BAPI_MATERIAL_SAVEREPLICA 替代 BAPI_MATERIAL_SAVEDATA
2、LOOP 里面delete,可以改成,给内表加一个flag的字段,然后需要删除的打上X,然后用Delete it_1 where delete = ‘X’.
3、LOOP AT 搭INSERT或者是APPEND,可以改成: INSERT SBOOK FROM TABLE itab。 APPEND LINES
4、如果是两个内表都很多数据,但是逻辑要进行嵌套LOOP,可以如下处理,会提升一些性能:
方法一:
sort itab2 by aa. 这个地方看上去像是两个LOOP,其实是只有一个。
loop itab1
read itab2 aa = itab-11 binary search.
loop itab2 from sy-taibx.
endloop.
endloop.
方法二:
方法三:
5、LOOP 后面用assigning 指针的方式,这样也可以节省空间和时间:可以省去了append,modify等操作,在嵌套LOOP没法像上面那样解决的话,也建议使用指针。
FIELD-SYMBOLS : <FS> TYPE VBAK.
LOOP AT gt_vbak ASSIGNING <FS> Where lifsk = '01'.
<fs>-space = '02'.
二、有一些标准的FM,如果在LOOP里面使用可以考虑换成使用自己开发,把抓数放出来,然后read(read_text):
1、有很多程序要调用FM read_text,但是当用到LOOP里面调用这个read_text,会比较慢其中到STXH表抓数就会占用很多时间,我们可以考虑对read_text进行优化,把read_text分成两个FM,一个是集中读取STXH,然后另一个是和read_text一样的功能,只是把抓数换成read table。占用性能就会提高很多。
三、一些优秀的良好的ABAP 程序书写习惯:
1、select 数据的时候,如果可以使用join进行内联,尽量2-3个表内联即可。
2、如果要select 数据出来,更改一些字段的值,再进行updata,可以考虑直接使用updata set,省去到表里面抓数:
SELECT * FROM sbook
INTO xbook
WHERE carrid = 'LH' AND connid = '0400' AND fldate >= '20110101'.
xbook-connid = '0500'.
UPDATE sbook FROM xbook.
ENDSELECT.
UPDATE sbook
SET connid = '0500' WHERE carrid = 'LH' AND connid = '0400' AND fldate >= '20110101'.
3、读取HASHED表会比其他两种类型更快,同时read table 也可以通过transporting 某些字段到work area,不用全部字段都用上。
4、有些表的数据,是很固定的,例如KNA1或者是T001等,可以抓大部分数据放到内表里,然后去读取,如果读取不到,在抓,不用每次都抓。
5、强制使用索引:(但是如果更改数据库了,就会失效了) %_HINTS DB6 (这个不太建议使用,但是当ST05分析之后,是可以使用某个索引,但系统没有使用,就可以使用这个语句强制使用索引。)
ABAP
6、当一个report在ALV显示完之后,在end-of-selection里面把不用的内表的清空掉,防止有些后台job一次跑两个变量的时候会重复,同时释放内表也是减少内存压力。
7、field-groups的使用,对于多层次的排序和显示非常有用。