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

2021-10-30 19:56发布


          点击此处--->   EasySAP.com 群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)

点击蓝字 关注我们

前言

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

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

几种方式

  • 标准表

  • 排序表

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

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

  • 两个排序表通过INDEX 优化

  • 二分查找优化

先说结论

通过测试:

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


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


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

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

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

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


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

内表A数据重复.

内表A数据不重复


测试程序功能说明

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

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

 LT_B中F1内容2次重复


几种方式详解



01

标准内表循环


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


02

排序表


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


03

嵌套哈希表


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


04

排序表按INDEX 优化


该方式需要对两个内表都排序, 性能最好, 代码逻辑有点复杂. 并且有使用限制, LT_A-F1内容不能重复(如果内表LT_A 中的F1 内容重复. 则后面的行无法获取数据 ). 使用时请务必确保LT_A 内容不重复.

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

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


05

二分查找后再循环


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



测试源代码

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

*&---------------------------------------------------------------------**& 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 lw_a. READ TABLE lt_b_h INTO lw_b_h WITH TABLE KEY f1 = lw_a-f1. LOOP AT lw_b_h-items INTO lw_items. CLEAR lw_c. lw_c-f1 = lw_a-f1. lw_c-f2 = lw_a-f2. lw_c-f3 = lw_items-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)'哈希表-GROUP构造:',lv_lines ,'总时间:', lv_micro,'微秒','构造表时间:', lv_micro2,'执行时间:', lv_micro3.ENDFORM.*&---------------------------------------------------------------------**& Form PROC_STANDARD_TAB*&---------------------------------------------------------------------**& text*&---------------------------------------------------------------------**& --> p1 text*& <-- p2 text*&---------------------------------------------------------------------*FORM proc_standard_tab . DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b, lw_c TYPE ty_c. GET RUN TIME FIELD DATA(t1). LOOP AT lt_a INTO lw_a. LOOP AT lt_b 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(t2). DATA: lv_lines TYPE i. lv_lines = lines( lt_c ). DATA: lv_micro TYPE i. lv_micro = t2 - t1. WRITE:/(20)'标准表: ',lv_lines ,'总时间:',lv_micro,'微秒'.ENDFORM.
FORM proc_standard_tab_2 . DATA: lw_a TYPE ty_a. DATA: lw_b TYPE ty_b, lw_c TYPE ty_c. GET RUN TIME FIELD DATA(t1). SORT lt_a BY f1. SORT lt_b BY f1.
GET RUN TIME FIELD DATA(t2). DATA: i TYPE i. i = 1. LOOP AT lt_a INTO lw_a. LOOP AT lt_b INTO lw_b FROM i. IF lw_b-f1 <> lw_a-f1. i = sy-tabix. EXIT. ENDIF. 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)'按index优化:',lv_lines ,'总时间:', lv_micro,'微秒','构造表时间:', lv_micro2,'执行时间:', lv_micro3..ENDFORM.

FORM proc_hashed_tab_2. 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). SORT lt_b BY f1. LOOP AT lt_b INTO lw_b. AT NEW f1. CLEAR lw_b_h. lw_b_h-f1 = lw_b-f1. ENDAT. APPEND lw_b TO lw_b_h-items. AT END OF f1. INSERT lw_b_h INTO TABLE lt_b_h. ENDAT. ENDLOOP. GET RUN TIME FIELD DATA(t2). LOOP AT lt_a INTO lw_a. READ TABLE lt_b_h INTO lw_b_h WITH TABLE KEY f1 = lw_a-f1. LOOP AT lw_b_h-items INTO lw_items. CLEAR lw_c. lw_c-f1 = lw_a-f1. lw_c-f2 = lw_a-f2. lw_c-f3 = lw_items-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)'哈希表-AT NEW构造:',lv_lines ,'总时间:', lv_micro,'微秒','构造表时间:', lv_micro2,'执行时间:', lv_micro3..ENDFORM.



THE

END

约定

如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.       

    (如果你真的喜欢这篇文章,请记得回来打个赏,作为支持我继续下去的动力,这是一个正反馈过程. 越多的人打赏,作者越有动力分享,读者就能享受更多的福利.毕竟打赏的金额富不了我,穷不了你,却能支持这个公众号长久发文.)



公众号 : syjf1976_abap

          ABAP开发技巧

微信号 : 392077


公众号主群加入受限, 请扫码加入副群后,向管理员申请加入主群

赞赏支持