原创 Tab Zhu [ SAP TAB ](javascript:void\(0\);)
**点击蓝字关注我们**
富强 民主 文明 和谐
自由 平等 公正 法制
爱国 敬业 诚信 友善
_**ABAP
** _
**程序优化笔记**
**不念过** **去**
**START**
**不畏将来**
昨天做了一个别人的程序优化, 朋友圈小伙伴留言,写出来看看是如何优化的。
取数逻辑上基本都改了。做这个程序优化真是痛并快乐着,首先拿到一个程序,不完全不知道逻辑,那么首先得看懂它的逻辑,然后想办法去优化。趁着这次机会,写一下ABAP的优化吧。
总的来说,对于S4 HANA 数据库执行要优于应用层的执行,但是我们需要减少数据库和应用层的交互次数。
## 1.尽量明确自己要取得字段,
优化之前 | 优化之后
---|---
SELECT * FROM LIPS INTO TABLE @ITAB WHERE ··· | SELECT VBELN,POSNR,MATNR INTO TABLE @ITAB WHERE ···## 2.在select 查询时,特别是需要经过选择界面筛选处理的,尽量使用inner join ( left outer join)
一次性抓取出来。别使用for all entries in。
如:选择屏幕上有
SELECT-OPTIONS : S_WADAT FOR LIKP \- WADAT OBLIGATORY , _ " _ _ 交货日期S_DN FOR LIKP \- VBELN , _ " _ _ 交货订单 _ S_BSART FOR EKKO \- BSART
, _ " STO _ _ 类型 _
S_EBELN FOR EKKO \- EBELN , _ " _ _ 调拨单号 _ S_VBELN FOR VBAK \-
VBELN , _ " _ _ 销售订单号 _ S_VKBUR FOR VBAK \- VKBUR , _ " _ _ 销售据点 _
S_AUART FOR VBAK \- AUART. _ " _ _ 销售订单类型 _
---
• 我们可以直接写 sql SELECT A ~ VBELN , A ~ VSTEL , A ~ LFDAT , A ~ WADAT , A ~ LFART ,
A ~ WADAT_IST , A ~ VSBED , A ~ ERNAM , A ~ ERDAT , A ~
ERZET ,
B ~ WERKS , B ~ VRKME , B ~ VGBEL , B ~ POSNR , B ~ VGTYP ,
B ~ MEINS ,
B ~ BRGEW , B ~ LGMNG , B ~ MATNR , B ~ VTWEG , B ~ SPART ,
B ~ MVGR2 , B ~ SHKZG , B ~ MTART ,
C~EBELN , C~BSART , C~BSTYP , C~UNSEZ,
D ~ VBELN AS VBELN_SO , D ~ AUART , D ~ ZZTRANUM , D ~ VKBUR
, D ~ ZZCHGROUP
FROM LIKP AS A
INNER JOIN LIPS AS B ON B ~ VBELN = A ~ VBELN
LEFT JOIN EKKO AS C ON C ~ EBELN = B ~ VGBEL
LEFT JOIN VBAK AS D ON D ~ VBELN = B ~ VGBEL
INTO TABLE @LT_LIPS
WHERE WADAT IN @S_WADAT AND A ~ VBELN IN @S_DN AND B ~ LGMNG > 0
AND C ~ EBELN IN @S_EBELN AND C ~ BSART IN @S_BSART
AND D ~ VBELN IN @S_VBELN AND D ~ VKBUR IN @S_VKBUR AND D ~
AUART IN @S_AUART.
## 3.在写for all entries in 的时候注意点
1\. 写全你要所要取数据的主键,来保证每条数据是唯一的,因为 forall entries in 自带 selectdistinct 去重功能
.( 直接把所要取得表得主键都写上呗 )
2\. 先判断下 for allentries in itab 这个表是否为空, ifitab[] is not initial 一定要有,这个
ABAPer 应该都知道
DATA ( LT_DATA_MATNR ) = GT_DATA[] .
SORT LT_DATA_MATNR BY MATNR .
DELETE ADJACENT DUPLICATES FROM LT_DATA_MATNR COMPARING MATNR .
SELECT A ~ MATNR A ~ MTART A ~ BISMT B ~ MAKTX INTO TABLE LT_MAFROM MARA AS A
LEFT OUTER JOIN MAKT AS B ON A ~ MATNR = B ~ MATNR AND B ~
SPRAS = SY \- LANGU
FOR ALL ENTRIES IN LT_DATA_MATNR
WHERE A ~ MATNR = LT_DATA_MATNR \- MATNR .
---
4.for all entries in 非常消耗内存,当 itab 过大的时候不建议使用,若是你一定要用请这么操作:(当 itab
过大时,会引起资源瓶颈)
DATA LV_LINES TYPE I. SORT LT_PARTNER BY TABLE_LINE .
DELETE ADJACENT DUPLICATES FROM LT_PARTNER COMPARING ALL FIELDS .
DESCRIBE TABLE LT_PARTNER[] LINES DATA ( LV_LINES ).
IF LV_LINES LE 3000 .
SELECT PARTNER NAME_ORG1 FROM BUT000 INTO TABLE LT_BUT000FOR ALL ENTRIES IN LT_PARTNER
WHERE PARTNER = LT_PARTNER \- TABLE_LINE .
ELSE .
CLEAR : LV_TIMES , LT_PARTNER_TMP .
LOOP AT LT_PARTNER INTO DATA ( LS_PARTNER ).LV_TIMES = LV_TIMES + 1 .
APPEND LS_PARTNER TO LT_PARTNER_TMP .
IF LV_TIMES GE 3000 .CHECK LT_PARTNER_TMP[] IS NOT INITIAL .
SELECT PARTNER NAME_ORG1 FROM BUT000 APPENDING TABLE LT_BUT000FOR ALL ENTRIES IN LT_PARTNER_TMP
WHERE PARTNER = LT_PARTNER_TMP \- TABLE_LINE .
CLEAR : LV_TIMES , LT_PARTNER_TMP .
ENDIF .AT LAST .
CHECK LT_PARTNER_TMP[] IS NOT INITIAL .
SELECT PARTNER NAME_ORG1 FROM BUT000 APPENDING TABLE LT_BUT000FOR ALL ENTRIES IN LT_PARTNER_TMP
WHERE PARTNER = LT_PARTNER_TMP \- TABLE_LINE .
CLEAR : LV_TIMES , LT_PARTNER_TMP .
ENDAT .
ENDLOOP .
ENDIF .---
## 4.内表的使用方面
a) 尽量使用hash表,其次是sort表,然后再是standard表
注:尽量使用sort表吧,实际实施过程中,哈希表用的还是很少的,很多时候我们需要很灵活的对表进行各种字段排序,Sort表的插入数据会比标准表要耗时。
b) 使用 LOOP AT GT_OUT ASSIGNING FIELD-SYMBOL(<FS>).会比使用
into要好,特别是需要修改数据的时候。当然用loop at itab , at end of , sum求和不能使用<fs>了。
使用<fs>时,遇到at end of 操作,<fs>中数据不会变成*
c) 常用: read table 时 注意排序,然后使用binary search来提高效率
它的升级版就是提升双层loop的效率,这个在合计值和子表不止一个值和主表对应时比较好用。
SORT GT_OUT by vbeln. SORT LT_DN BY VBELN. LOOP AT GT_OUT ASSIGNING
FIELD \- SYMBOL ( <FS> ). READ TABLE LT_DN TRANSPORTING NO FIELDS WITH
KEY VBELN = <FS> \- VBELN BINARY SEARCH .
IF SY \- SUBRC EQ 0 .LV_TABIX = SY \- TABIX .
LOOP AT LT_DN INTO LS_DN FROM LV_TABIX .
IF LS_DN-V BELN = <FS> \- VBELN .<FS>-MENGE = <FS>-MENGE + LS_DN-MENGE.
ELSE .
EXIT .
ENDIF .
ENDLOOP .
ENDIF . ENDLOOP.---
d) 对内表进行删除操作时,最好这么操作
LOOP AT LT_DATA ASSIGNING FIELD \- SYMBOL ( <FS> ).
READ TABLE LT_DATA_1 TRANSPORTING NO FIELDS WITH KEY VBELN_DN = <FS> \-VBELN_DN BINARY SEARCH .
IF SY \- SUBRC <> 0 .<FS> \- DEL_FLG = 'X' .
ENDIF .
ENDLOOP . DELETE LT_DATA WHERE DEL_FLG = 'X' .---
e) 合计值的时候使用collect
这个语句还是挺高效的。
SELECT A ~ VBELN AS VBELN_DN , B ~ ERDAT , A ~ POSNR ASPOSNR_DN , A ~ MATNR , A ~ LFIMG
FROM LIPS AS A
INNER JOIN LIKP AS B ON B ~ VBELN = A ~ VBELN
INTO TABLE @LT_DATA .
_ * _
SORT LT_DATA BY MATNR .
LOOP AT LT_DATA ASSIGNING FIELD \- SYMBOL ( <FS> ).LS_MATNR \- MATNR = <FS> \- MATNR .
LS_MATNR \- LFIMG = <FS> \- LFIMG .
COLLECT LS_MATNR INTO LT_MATNR .
ENDLOOP .---
合计6W多条数据:
同时新语法:LOOP AT GROUP 在合计方面也是挺好使用得
LOOP AT LT_DATA ASSIGNING FIELD \- SYMBOL ( <FS1> ) GROUP BY ( MATNR= <FS1> \- MATNR
SIZE = GROUP SIZE INDEX = GROUP INDEX ) ASCENDING ASSIGNING FIELD \-
SYMBOL ( <GROUP> ).
LS_MATNR \- MATNR = <GROUP> \- MATNR .
LOOP AT GROUP <GROUP> ASSIGNING FIELD \- SYMBOL ( <FS2> ).LS_MATNR \- LFIMG = <FS2> \- LFIMG + LS_MATNR \- LFIMG .
ENDLOOP .
APPEND LS_MATNR TO LT_MATNR .CLEAR LS_MATNR .
ENDLOOP .---
同样的数据,相对比collet还是要逊色一点
但是下面这个图就让我体会了一把HANA数据库的强大
代码是:
DATA : BEGIN OF LS_MATNR ,
MATNR TYPE LIPS \- MATNR ,
LFIMG TYPE LIPS \- LFIMG ,
END OF LS_MATNR .DATA LT_MATNR LIKE TABLE OF LS_MATNR .
SELECT MATNR , SUM ( LFIMG ) INTO TABLE @LT_MATNRFROM LIPS
GROUP BY MATNR . “听说网上都是避免使用 group by ,在 HANA 上不存在的
---
## 5.使用SE30和 ST05取分析程序各个部分的执行时间
进入SE30:选择OLD SE30,点击左下角的分析,你可以看到程序的ABAP时间和DB时间
现在一般使用新得SE30,可以看到每个部分执行得时间,进而进行优化
**不念过** **去**
**END**
**不畏将来**
**SAP ABAP TAB**
微信号 : TAB_JXZHU
后台回复’ABAP‘领取学习资料哈
长按二维码关注我们