ABAP 程序性能相关代码规范

SQL语句

 SELECT语句结构请遵循以下写法

SELECT 表1~字段11~字段2
INTO 内表或者结构
FROM 表或视图
INNER JION 表或视图 ON 条件
FOR ALL ENTIERS 内表
WHERE 条件

1、始终把条件放在where子句中而不要使用check语句来检查,这样数据库系统可以使用索引(如果可能),同时这样可以大大降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT * FROM SBOOK INTO SBOOK_WA.
  CHECK: SBOOK_WA-CARRID = 'LH' AND
         SBOOK_WA-CONNID = '0400'.
ENDSELECT.

Acceptable(正确示例):

SELECT * FROM SBOOK  INTO TABLE LT_SBOOK 
WHERE SBOOK~CARRID = ‘LH’
  AND SBOOK~CONNID =0400.

LOOP AT LT_SBOOK INTO LS_SBOOK.
......具体处理逻辑
ENDLOOP.

2、如果需要检查表或视图是否有满足某条件的记录存在,请使用Select … Up To 1 Rows 语句,而不要使用带Exit的Select-Endselect-loop语句。如果条件中包含所有的主键字段,则应该使用Select Single语句。Select Single语句仅需要与数据库通信一次,而 Select-Endselect则需要两次。
Example:
UnAcceptable(禁止使用):

SELECT * FROM SBOOK INTO GS_SBOOK
    WHERE CARRID = 'LH'.
  EXIT.
ENDSELECT.
IF SY-SUBRC = 0.

ENDIF.

Acceptable(正确示例):

SELECT SINGLE * FROM SBOOK INTO GS_SBOOK
 WHERE CARRID = 'LH'.
IF SY-SUBRC = 0.

ENDIF.

3、如果想查询最大值、最小值、总和、平均值或者条目数,则应该使用统计函数;这样可以大大降低网络负载。
Example:
UnAcceptable(禁止使用):

DATA: MAX_MSGNR type t100-msgnr.
MAX_MSGNR = '000'.
SELECT * FROM T100 INTO T100_WA
  WHERE SPRSL = 'D' AND
        ARBGB = '00'.
  CHECK: T100_WA-MSGNR > MAX_MSGNR.
  MAX_MSGNR = T100_WA-MSGNR.
ENDSELECT.

Acceptable(正确示例):

DATA: LV_MAX_MSGNR type t100-msgnr.
SELECT MAX( MSGNR ) FROM T100 INTO LV_MAX_MSGNR
  WHERE SPRSL = 'D' 
AND  ARBGB = '00'.

4、如果仅需读取表或视图中的个别字段,那么应该使用select列表而不要使用Select * ;这样可以大大降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT * FROM DD01L INTO LS_DOM
  WHERE DOMNAME LIKE 'CHAR%'
    AND AS4LOCAL = 'A'.
 APPEND LS_DOM TO GT_DOM
ENDSELECT.

Acceptable(正确示例):

SELECT DOMNAME FROM DD01L
INTO TABLE GT_DOM
WHERE DOMNAME LIKE 'CHAR%'
  AND AS4LOCAL = 'A'.

5、更新数据库时,尽可能使用列更新而不要使用单行更新。这样可以大大降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT * FROM SFLIGHT INTO LS_SFLIGHT
  LS_SFLIGHT-SEATSOCC =  LS_SFLIGHT-SEATSOCC - 1.
  UPDATE SFLIGHT FROM LS_SFLIGHT.
ENDSELECT.

Acceptable(正确示例):

LV_SEATSOCC = LV_SEATSOCC – 1.
UPDATE SFLIGHT
SET SEATSOCC = LV_SEATSOCC
WHERE FKEY = LV_FKEY.

6、对于经常使用的数据表,优先使用表主键,且尽量按表主键顺序作为查询条件;其次使用表索引。在select语句的where子句中,尽量使用通过AND连接的索引字段,这样数据库总是会使用索引。注意:过于复杂的where子句对于数据库系统语句优化器来说都是不利于处理的。
Example:
UnAcceptable(禁止使用):

SELECT * FROM SBOOK CLIENT SPECIFIED INTO GS_SBOOK
  WHERE CARRID = 'LH'
    AND CONNID = '0400'.
ENDSELECT.

Acceptable(正确示例):

SELECT SINGLE * FROM SBOOK CLIENT SPECIFIED INTO GS_SBOOK
  WHERE MANDT  =100AND CARRID = 'LH'
    AND CONNID = '0400'.

7、对于经常使用的只读表,尽量使用SAP缓存。可以大大降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT SINGLE * FROM T100 INTO T100_WA
  BYPASSING BUFFER
  WHERE SPRSL = 'D'
    AND ARBGB = '00'
    AND MSGNR = '999'.

Acceptable(正确示例):

 SELECT MANDT INTO TABLE GT_T000 FROM T000.
 SELECT * FROM SBOOK CLIENT SPECIFIED INTO TABLE GT_SBOOK
  FOR ALL ENTRIES IN GT_T000
  WHERE MANDT = GT_T000-MANDT
         AND CARRID = 'LH'
         AND CONNID = '0400'. 
LOOP AT GT_SBOOK INTO GS_SBOOK.
    ...
ENDLOOP.

8、一般情况下使用Into Table总是会快于Select循环中使用Append 语句。
Example:
UnAcceptable(禁止使用):

SELECT * FROM T006 INTO LS_T006.
  APPEND LS_T006 TO LT_T006.
ENDSELECT.

Acceptable(正确示例):

SELECT * FROM T006 
INTO TABLE LT_T006.

9、更新数据库表时,尽可能使用数组操作而不要使用单行操作。应用程序和数据库系统频繁通信会造成大量的系统负载。
Example:
UnAcceptable(禁止使用):

LOOP AT LT_CUS INTO LS_CUS.
  INSERT INTO CUSTOMERS VALUES LS_CUS.
ENDLOOP.

Acceptable(正确示例):

INSERT CUSTOMERS FROM TABLE LT_CUS.

10、如果要处理表连接,应该使用视图而不要使用嵌套的select语句;这样可以有效的降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT * FROM DD01L INTO LS_DD01L
  WHERE DOMNAME LIKE 'CHAR%'
        AND AS4LOCAL = 'A'.
  SELECT SINGLE * FROM DD01T INTO LS_DD01T
    WHERE   DOMNAME    = LS_DD01L-DOMNAME
        AND AS4LOCAL   = 'A'
        AND AS4VERS    = LS_DD01L-AS4VERS
        AND DDLANGUAGE = SY-LANGU.
ENDSELECT.

Acceptable(正确示例):

SELECT * FROM DD01V INTO  LT_DD01V
WHERE DOMNAME LIKE 'CHAR%'
AND DDLANGUAGE = SY-LANGU.

11、如果要从几个逻辑关联的表中读取数据,应该使用表连接而不要使用嵌套的select语句;这样可以有效的降低网络负载。
Example:
UnAcceptable(禁止使用):

SELECT * FROM SPFLI INTO LS_SPFLI.
  SELECT * FROM SFLIGHT INTO LS_SFLIGHT
      WHERE CARRID = LS_SPFLI-CARRID
        AND CONNID = LS_SPFLI-CONNID.
  ENDSELECT.
ENDSELECT.

Acceptable(正确示例):

SELECT * INTO TABLE LT_FLIGHT     FROM SPFLI AS P INNER JOIN SFLIGHT AS F     ON  P~CARRID = F~CARRID      AND P~CONNID = F~CONNID.

12、使用For all entries in之前必须先判断内表是否为空。
Example:
UnAcceptable(禁止使用):

SELECT VBLEN POSNR
     INTO TABLE GT_SOITEM
       FROM VBAP
        FOR ALL ENTRIES IN GT_VBAK
         WHERE VBELN = GT_VBAK-VBELN. 

Acceptable(正确示例):

 IF NOT GT_VBAK[] IS INITIAL.
       SELECT VBLEN POSNR
       INTO TABLE  GT_SOITEM
       FROM VBAP
       FOR ALL ENTRIES IN GT_VBAK
       WHERE VBELN = GT_VBAK-VBELN.
     ENDIF.

内表操作

1、如果内表的记录条数很多(>20),那么对全表进行线性查询是非常费时的。应该尽量使内表排序,并使用二分法搜索,或者使用SORTED TABLE。假如内表含有n条记录,线性搜索执行时间为O( n ) ,而二分法执行时间仅为O( log2( n ) )。
Example:
UnAcceptable(不推荐使用):

* Entries: 1000, Line width: 100
*                Key width:   20
* The READ ends with SY-SUBRC=4

READ TABLE ITAB INTO WA
                WITH KEY K = 'X'.

Acceptable(正确示例):

* Entries: 1000, Line width: 100
*                Key width:   20
* The READ ends with SY-SUBRC=4

SORT LT_TAB BY K ASCENDING.
READ TABLE ITAB INTO WA
                WITH KEY K = 'X'
                BINARY SEARCH.

2、如果需要使用不同的关键字重复读取内表,那么应该在代码中保存相应的次级索引。有了次级索引就可以使用二分法搜索加上一个索引读取来替代线性搜索。
Example:
UnAcceptable(不推荐使用):

* Entries: 1000, Line width: 100
*                Key width:   20
* The READ locates the 500th entry.

READ TABLE ITAB INTO WA
     WITH KEY DATE = SY-DATUM.
IF SY-SUBRC = 0.
  " ...
ENDIF.

Acceptable(正确示例):

* Entries: 1000, Line width: 100
*                Key width:   20
* The READ locates the 500th entry.

READ TABLE SEC_IDX INTO  SEC_IDX_WA
     WITH KEY DATE = SY-DATUM
          BINARY SEARCH.
IF SY-SUBRC = 0.
  READ TABLE ITAB INTO WA
                  INDEX SEC_IDX_WA-INDX.
  " ...
ENDIF.

3、LOOP … WHERE比LOOP/CHECK性能更好,因为LOOP … WHERE由内部来判断指定的条件。同所有的逻辑表达式一样,如果操作数的类型相同,则性能会更好。 可能的情况下,使用FROM i1且(或者)TO i2可以进一步提高性能。
Example:
UnAcceptable(不推荐使用):

* Entries: 1000, Line width: 500
*                Key width:   20
* 5 entries of which match the key condition

LOOP AT ITAB INTO WA.
  CHECK WA-K = 'X'.
  " ...
ENDLOOP.

Acceptable(正确示例):

* Entries: 1000, Line width: 500
*                Key width:   20
* 5 entries of which match the key condition

LOOP AT ITAB INTO WA WHERE K = 'X'.
  " ...
ENDLOOP.

4、排序表中的记录通过二分法来定位,执行的时间依赖于表中记录数(O (log n))。而哈希表中记录通过哈希算法来定位,执行的时间始终是固定的(O (1)), 而与表的大小无关。 哈希表适用于单条记录的读取,而排序表则适用于符合部分条件的顺序的表循环操作。
Example:
UnAcceptable(不推荐使用):

* Entries: 1000
* Line width: 100, key width: 20
* STAB is a unique sorted table, 250 entries are read

DO 250 TIMES.
  N = 4 * SY-INDEX.
  READ TABLE STAB INTO WA WITH TABLE KEY K = N.
  IF SY-SUBRC = 0.
    " ...
  ENDIF.
ENDDO.

Acceptable(正确示例):

* Entries: 1000
* Line width: 100, key width: 20
* HTAB is a hased table, 250 entries are read

DO 250 TIMES.
  N = 4 * SY-INDEX.
  READ TABLE HTAB INTO WA WITH TABLE KEY K = N.
  IF SY-SUBRC = 0.
    " ...
  ENDIF.
ENDDO.

5、哈希表为单条记录读取而优化,记录之间没有特定的顺序关系。因此对哈希表进行部分键值的顺序读取,其性能是没有优化的,而是每一条记录都要检查是否符合条件(即全表搜索)。排序表则是按照主键进行升序排列的。如果查询条件是这样的格式"k1 = v1 AND … AND kn = vn"(k1 … kn与表主键的左边部分匹配),那么表的读取是被核心代码优化的,因此只会访问符合条件的记录,而不是全表搜索。
Example:
UnAcceptable(不推荐使用):

* Entries: 10000, Line width: 100
* key width: 60,  Subkey width: 20
* HTAB is a hashed table, 2000 entries are read
* Key fields: K, DATA

LOOP AT HTAB INTO WA WHERE K = SUBKEY.
  " ...
ENDLOOP.

Acceptable(正确示例):

* Entries: 10000, Line width: 100
* key width: 60,  Subkey width: 20
* STAB is a sorted table, 2000 entries are read
* Key fields: K, DATA

LOOP AT STAB INTO WA WHERE K = SUBKEY.
  " ...
ENDLOOP.

6、使用MODIFY语句更新内表时,使用" TRANSPORTING f1 f2 …"可以提高执行的效率;特别是表行越长越明显。
Example:
UnAcceptable(不推荐使用):

* Line width: 500
* The complete line is moved.

WA-DATE = SY-DATUM.
MODIFY ITAB FROM WA INDEX 1.

Acceptable(正确示例):

* Line width: 500
* Only the 8 bytes of the selected
* component are moved.

WA-DATE = SY-DATUM.
MODIFY ITAB FROM WA INDEX 1 TRANSPORTING DATE.

7、使用"LOOP … ASSIGNING … "直接存取内表行,可以大大提高内表记录的更新速度。
Example:
Not preferred(不推荐使用):

* Entries: 100 (outer table), 20 (inner table)
* The entries to be modified: 50
* Actually, only the component FLAG is updated.
* However, the complete lines are moved.

LOOP AT ITAB INTO WA.
  I = SY-TABIX MOD 2.
  IF I = 0.
    WA-FLAG = 'X'.
    MODIFY ITAB FROM WA.
  ENDIF.
ENDLOOP.

Preferred(正确示例):

* Entries: 100 (outer table), 20 (inner table)
* Entries to be modified: 50
* The component FLAG is updated directly.

LOOP AT ITAB ASSIGNING <WA>.
  I = SY-TABIX MOD 2.
  IF I = 0.
    <WA>-FLAG = 'X'.
  ENDIF.
ENDLOOP.

8、使用从下到上的策略来填充内表,那么系统开销会根据数据结构的层次成倍的增加。因为每一个下层内表的数据都需要移动到它们的上层数据结构中。相反,使用从上到下的策略填充内表,先填充外层内表,然后使用"LOOP … ASSIGNING"直接填充内层内表,这样内层内表的数据只需要移动一次就可以了。
Example:
Not preferred(不推荐使用):

* Entries: 50 (outer table), 10 (inner tables)
* Line width: 500 (outer), 4 (inner)

DO 50 TIMES.
  CLEAR WA.
  DO 10 TIMES.
    APPEND N TO WA-INTTAB.
    ADD 1 TO N.
  ENDDO.
  APPEND WA TO ITAB.
ENDDO.

Preferred(正确示例):

* Entries: 50 (outer table), 10 (inner tables)
* Line width: 500 (outer), 4 (inner)

DO 50 TIMES.
  APPEND INITIAL LINE TO ITAB.
ENDDO.
LOOP AT ITAB ASSIGNING <F>.
  DO 10 TIMES.
    APPEND N TO <F>-INTTAB.
    ADD 1 TO N.
  ENDDO.
ENDLOOP.

9、如果需要汇总表记录,那么请使用COLLECT语句,把字符类型字段放在前面,数值型字段放后面。
Example:
UnAcceptable(不推荐使用):

* TAB1: 1000 entries, Line width: 32
* 500 entries have different keys

LOOP AT LT_TAB1 INTO LS_TAB1.
READ TABLE LT_TAB2 INTO LS_TAB2 WITH KEY K = LS_TAB1-K BINARY SEARCH.
IF SY-SUBRC = 0.
  ADD: LS_TAB1-VAL1 TO LS_TAB2-VAL1,
       LS_TAB1-VAL2 TO LS_TAB2-VAL2.
  MODIFY LT_TAB2 FROM LS_TAB2 INDEX SY-TABIX TRANSPORTING VAL1 VAL2.
ELSE.
  INSERT LS_TAB1 INTO LT_TAB2 INDEX SY-TABIX.
ENDIF.
ENDLOOP. 

Acceptable(正确示例):

* TAB1: 1000 entries, Line width: 32
* 500 entries have different keys

LOOP AT LT_TAB1 INTO LS_TAB.
      COLLECT LS_TAB INTO LT_TAB2.
    ENDLOOP.
   SORT LT_TAB2 BY K. 

10、如果要将一个表的记录追加到另一个表中,请使用"APPEND LINES OF itab1 TO itab2" .
Example:
UnAcceptable(不推荐使用):

* Entries: 500 (ITAB1), 500 (ITAB2)
* Line width: 500
* ITAB1 is appended line by line to ITAB2.

LOOP AT LT_TAB2 INTO LS_TAB.
   APPEND LS_TAB TO LT_TAB2.
 ENDLOOP. 

Acceptable(正确示例):

* Entries: 500 (ITAB1), 500 (ITAB2)
* Line width: 500
* ITAB1 is appended in one step to ITAB2.

APPEND LINES OF LT_TAB1 TO LT_TAB2. 

11、 复制内表可以像其他数据类型一样使用MOVE语句。
Example:
UnAcceptable(不推荐使用):

* Entries: 100, Line width 100

REFRESH LT_TAB2.
LOOP AT LT_TAB1 INTO LS_TAB1.
  APPEND LS_TAB1 TO LT_TAB2.
ENDLOOP. 

Acceptable(正确示例):

* Entries: 100, Line width 100

LT_TAB2[] = LT_TAB1[]. 

12、 对于sort语句,请指定排序的字段。
Example:
UnAcceptable(不推荐使用):

* Entries: 100, Line width: 500
* Key width: 492

SORT LT_TAB.

Acceptable(正确示例):

* Entries: 100, Line width: 500
* Key width: 20

SORT LT_TAB BY K.

其他语句

CASE语句

CASE 相对于IF语句更清晰易读,性能也稍好一些。
Example:
UnAcceptable(不推荐使用):

DATA C TYPE C.
 IF     C = 'A'.   WRITE '1'.
 ELSEIF C = 'B'.   WRITE '2'.
 ELSEIF C = 'C'.   WRITE '3'.
 ELSEIF C = 'D'.   WRITE '4'.
 ELSEIF C = 'E'.   WRITE '5'.
 ELSEIF C = 'F'.   WRITE '6'.
 ELSEIF C = 'G'.   WRITE '7'.
 ELSEIF C = 'H'.   WRITE '8'.
 ELSE. WRITE ‘9.
 ENDIF.

Acceptable(正确示例):

DATA C TYPE C.
 CASE C.
   WHEN 'A'. WRITE '1'.
   WHEN 'B'. WRITE '2'.
   WHEN 'C'. WRITE '3'.
   WHEN 'D'. WRITE '4'.
   WHEN 'E'. WRITE '5'.
   WHEN 'F'. WRITE '6'.
   WHEN 'G'. WRITE '7'.
   WHEN 'H'. WRITE '8'.
   WHEN OTHERS. WRITE ‘9.
 ENDCASE.

WHILE语句

如果可以使用WHILE语句来替换DO+EXIT语句,那么请使用WHILE语句,因为WHILE语句更易读且性能也要好一些。
Example:
UnAcceptable(不推荐使用):

DATA C TYPE C. DATA I TYPE I.
 I = 0.
 DO.
    IF C NE SPACE. EXIT. ENDIF.
    ADD 1 TO I.
    IF I GT 10. C = 'X'. ENDIF.
 ENDDO.

Acceptable(正确示例):

DATA C TYPE C. DATA I TYPE I.
 I = 0.
 WHILE C = SPACE.
    ADD 1 TO I.
    IF I GT 10. C = 'X'. ENDIF.
 ENDWHILE.

比较语句

比较语句中的两操作数尽量使用相同的数据类型,比如字符与字符的比较性能比字符与数字的比较更好。
Example:
UnAcceptable(禁止使用):

DATA C8) TYPE C.
 IF 12345678 = C.
 ENDIF.

Acceptable(正确示例):

DATA C8) TYPE C.
 IF '12345678' = C.
 ENDIF.
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值