SAP 小技巧双 LOOP 循环的性能优化

作者:ABAP技巧与实战 约 7 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:Basis, 系统管理

原创 无峰 [ ABAP 技巧与实战 ](javascript:void\(0\);)

**点击蓝字** 关注我们

前言

昨天转发一篇关于嵌套哈希内表优化两个内表循环的文章. 公众号讨论区中引起了一场讨论. 网友孙亮 给出了一个更优化的方式.多谢他的指正.

**本文给出几种双内表LOOP循环的方式并比较一下优劣.**

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

几种方式

• 标准表

• 排序表

• 嵌套哈希内表- GROUP BY 语句 构造

• 嵌套哈希内表- AT NEW 语句 构造

• 两个排序表通过INDEX 优化

• 二分查找优化

先说结论

通过测试

双排序表通过 index 优化的方式性能最优.(建议有经验的开发采用这种方式).但是该方式对数据有要求: LT_A 内表中的数据不能重复.

**通常情况,建议采用二分查找后循环的方式.**

**

**

如果构造的哈希表在程序中会被复用. 则建议构造哈希表后执行.

因为哈希表的构造耗时较大, 但是执行时间较低. 好于排序表及二分查找优化循环.

也可以只构造一个嵌套的哈希索引表(ITEMS中只存放原表的位置)

数据量大时,建议使用AT NEW 构造嵌套哈希内表

备注: 构造表指对所需的表排序,或构造嵌套哈希内表.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

内表A数据重复.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

内表A数据不重复

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

测试程序功能说明

内表LT_A 字段 F1 关联内表LT_B 字段 F1. 内容联合放入内表 LT_C

其中LT_A中F1字段按选择条件只出现一次或出现多次.

LT_B中F1内容2次重复

几种方式详解

_**01** _

**标准内表循环**

无需对数据执行任何加工. 逻辑最简单, 但是性能最差.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

_**02** _

**排序表**

需要定义一个排序表,通过赋值语句构造排序表,逻辑较简单,性能较好.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

_**03** _

**嵌套哈希表**

需要构造一个哈希嵌套表,可以通过 GROUP BY 语句构造, 也可以用AT NEW 构造. 逻辑比较复杂, 性能较好 (通过AT NEW

构造比通过GROUP BY 语句构造性能更好 ),但是构造耗时较长.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

_**04** _

**排序表按INDEX 优化**

该方式需要对两个内表都排序, 性能最好, 代码逻辑有点复杂. 并且有使用限制, **LT_A-F1内容不能重复** (如果内表LT_A 中的F1 内容重复.

则后面的行无法获取数据 ). 使用时请务必确保LT_A 内容不重复.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

**如下图: 如果LT_A 内容重复. 则INDEX 优化的方式最终获取的内容就不正确了.**

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

下图中的红框数字是最终内表LT_C的行数.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

_**05** _

**二分查找后再循环**

对内表LT_B 排序. 代码复杂度低, 性能更好. **建议采用此方式.** 需要注意:关键字比较不同之后退出子循环.

SAP 小技巧双 LOOP 循环的性能优化 - 封面图
SAP 小技巧双 LOOP 循环的性能优化 - 封面图

测试源代码

有兴趣的朋友,可以用下面的源代码测试一下几种方式的差异及性能.

*&---------------------------------------------------------------------**& Report ZTS_INTERAL_TABLE_PROC*&---------------------------------------------------------------------**&内表LT_A 字段 F1 关联内表LT_B 字段 F1. 内容联合放入内表 LT_C*其中LT_A中F1字段按选择条件只出现一次或出现多次.* LT_B中F1内容2次重复*&---------------------------------------------------------------------*REPORT zts_interal_table_proc.PARAMETERS: p_int TYPE i DEFAULT 1000.PARAMETERS: p_dup_a AS CHECKBOX.

INITIALIZATION. %_p_int_%_app_%-text = '内表条数'. %_p_dup_a_%_app_%-text = '内表A数据重复'. TYPES:BEGIN OF ty_a, f1(10), f2(10), END OF ty_a. TYPES: ty_a_tab TYPE TABLE OF ty_a. DATA: lt_a TYPE TABLE OF ty_a. TYPES:BEGIN OF ty_b, f1(10), f3(10), END OF ty_b. TYPES: ty_b_tab TYPE TABLE OF ty_b. DATA: lt_b TYPE TABLE OF ty_b.
TYPES:BEGIN OF ty_c, f1(10), f2(10), f3(10), END OF ty_c. TYPES: ty_c_tab TYPE TABLE OF ty_c. DATA: lt_c TYPE TABLE OF ty_c.

START-OF-SELECTION.

*构造内表数据 PERFORM frm_get_a_b CHANGING lt_a lt_b.*标准表方式 IF p_int <= 10000. REFRESH lt_c. PERFORM proc_standard_tab. ENDIF.*排序表方式 REFRESH lt_c. PERFORM proc_sort_tab. REFRESH lt_c.*构造嵌套哈希表方式- group 构造 PERFORM proc_hashed_tab.*构造嵌套哈希表方法- at new 构造 REFRESH lt_c. PERFORM proc_hashed_tab_2.*按性能帮助中的方法 REFRESH lt_c. PERFORM proc_standard_tab_2.*二分法查找, 再读取. REFRESH lt_c. PERFORM proc_sort_tab_2. *&---------------------------------------------------------------------**& Form FRM_GET_A*&---------------------------------------------------------------------**& text*&---------------------------------------------------------------------**& --> LT_A*&---------------------------------------------------------------------*FORM frm_get_a_b CHANGING ct_a TYPE ty_a_tab ct_b TYPE ty_b_tab. DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b. DATA: lv_numc(9) TYPE n. DO p_int TIMES. lv_numc = sy-index. CLEAR lw_a. lw_a-f1 = 'A' && lv_numc. lw_a-f2 = 'B' && lv_numc. APPEND lw_a TO ct_a. IF p_dup_a = 'X'. APPEND lw_a TO ct_a. ENDIF. lw_b-f1 = lw_a-f1. lw_b-f3 = 'C' && lv_numc. APPEND lw_b TO lt_b. lw_b-f1 = lw_a-f1. lw_b-f3 = 'D' && lv_numc. APPEND lw_b TO lt_b. ENDDO.ENDFORM.*&---------------------------------------------------------------------**& Form PROC_SORT_TAB*&---------------------------------------------------------------------**& text*&---------------------------------------------------------------------**& --> p1 text*& <-- p2 text*&---------------------------------------------------------------------*FORM proc_sort_tab . DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b, lw_c TYPE ty_c. DATA: lt_b_sort TYPE SORTED TABLE OF ty_b WITH NON-UNIQUE KEY f1. GET RUN TIME FIELD DATA(t1). SORT lt_b BY f1. lt_b_sort[] = lt_b[]. GET RUN TIME FIELD DATA(t2). LOOP AT lt_a INTO lw_a. LOOP AT lt_b_sort INTO lw_b WHERE f1 = lw_a-f1 . CLEAR lw_c. lw_c-f1 = lw_a-f1. lw_c-f2 = lw_a-f2. lw_c-f3 = lw_b-f3. APPEND lw_c TO lt_c. ENDLOOP. ENDLOOP. GET RUN TIME FIELD DATA(t3). DATA: lv_lines TYPE i. lv_lines = lines( lt_c ). DATA: lv_micro TYPE i, lv_micro2 TYPE i, lv_micro3 TYPE i. lv_micro = t3 - t1. lv_micro2 = t2 - t1. lv_micro3 = t3 - t2. WRITE:/(20)'排序表: ',lv_lines ,'总时间:', lv_micro,'微秒','构造表时间:', lv_micro2,'执行时间:', lv_micro3.ENDFORM. FORM proc_sort_tab_2 . DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b, lw_c TYPE ty_c. DATA: lt_b_sort TYPE SORTED TABLE OF ty_b WITH NON-UNIQUE KEY f1. GET RUN TIME FIELD DATA(t1). SORT lt_b BY f1. GET RUN TIME FIELD DATA(t2). LOOP AT lt_a INTO lw_a. READ TABLE lt_b TRANSPORTING NO FIELDS WITH KEY f1 = lw_a-f1 BINARY SEARCH. IF sy-subrc = 0. LOOP AT lt_b INTO lw_b FROM sy-tabix. IF lw_b-f1 <> lw_a-f1. EXIT. ENDIF. CLEAR lw_c. lw_c-f1 = lw_a-f1. lw_c-f2 = lw_a-f2. lw_c-f3 = lw_b-f3. APPEND lw_c TO lt_c. ENDLOOP. ENDIF. ENDLOOP. GET RUN TIME FIELD DATA(t3). DATA: lv_lines TYPE i. lv_lines = lines( lt_c ). DATA: lv_micro TYPE i, lv_micro2 TYPE i, lv_micro3 TYPE i. lv_micro = t3 - t1. lv_micro2 = t2 - t1. lv_micro3 = t3 - t2. WRITE:/(20)'二分查找优化循环: ',lv_lines ,'总时间:', lv_micro,'微秒','构造表时间:', lv_micro2,'执行时间:', lv_micro3.ENDFORM.*&---------------------------------------------------------------------**& Form PROC_HASHED_TAB*&---------------------------------------------------------------------**& text*&---------------------------------------------------------------------**& --> p1 text*& <-- p2 text*&---------------------------------------------------------------------*FORM proc_hashed_tab . DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b, lw_c TYPE ty_c. DATA: BEGIN OF lw_b_h, f1(10), items TYPE ty_b_tab, END OF lw_b_h. DATA: lw_items TYPE ty_b. DATA: lt_b_h LIKE HASHED TABLE OF lw_b_h WITH UNIQUE KEY f1. GET RUN TIME FIELD DATA(t1). LOOP AT lt_b INTO DATA(lw_gp) GROUP BY ( f1 = lw_gp-f1 ). CLEAR lw_b_h. lw_b_h-f1 = lw_gp-f1. LOOP AT GROUP lw_gp INTO lw_b. APPEND lw_b TO lw_b_h-items. ENDLOOP. INSERT lw_b_h INTO TABLE lt_b_h. ENDLOOP.

GET RUN TIME FIELD DATA(t2). LOOP AT lt_a INTO l

...

ABAP技巧与实战

关于作者:ABAP技巧与实战

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「SAP小技巧双LOOP循环的性能优化.md」整理生成,仅用于内部技术分享与学习交流。