双LOOP循环的性能优化
平时开发过程中遇到一些复杂的逻辑可能避免不了要用双LOOP循环的场景,这种情况下程序的性能是个很大的问题。数据量大一点的程序动辄3-5分钟,更有甚者直接跑到time out。
最近我学习整理了几种双LOOP循环性能优化的方法,在这里记录并分享一下。
首先,我们写一段没有经过优化的双LOOP循环来看看效果。
1 REPORT test_loop. 2 3 TYPES:BEGIN OF ty_a, 4 col1(10), 5 col2(10), 6 END OF ty_a, 7 BEGIN OF ty_b, 8 col1(10), 9 col3(10), 10 END OF ty_b, 11 BEGIN OF ty_c, 12 col1(10), 13 col2(10), 14 col3(10), 15 END OF ty_c. 16 17 DATA:wa_a TYPE ty_a, 18 wa_b TYPE ty_b, 19 wa_c TYPE ty_c, 20 gt_a TYPE TABLE OF ty_a, 21 gt_b TYPE TABLE OF ty_b, 22 gt_c TYPE TABLE OF ty_c. 23 24 START-OF-SELECTION. 25 26 PERFORM frm_getdata. 27 PERFORM frm_loop. 28 29 FORM frm_getdata. 30 DATA lv_line(5) TYPE n. 31 32 DO 5000 TIMES. 33 lv_line = sy-index. 34 35 CLEAR wa_a. 36 wa_a-col1 = 'col1'&& lv_line. 37 wa_a-col2 = 'col2'&& lv_line. 38 APPEND wa_a TO gt_a. 39 40 CLEAR wa_b. 41 wa_b-col1 = 'col1'&& lv_line. 42 wa_b-col3 = 'col3'&& lv_line. 43 APPEND wa_b TO gt_b. 44 ENDDO. 45 ENDFORM. 46 47 FORM frm_loop. 48 DATA lv_t TYPE i. 49 GET RUN TIME FIELD DATA(time1). 50 LOOP AT gt_a INTO wa_a. 51 LOOP AT gt_b INTO wa_b WHERE col1 = wa_a-col1. 52 wa_c-col1 = wa_a-col1. 53 wa_c-col2 = wa_a-col2. 54 wa_c-col3 = wa_b-col3. 55 APPEND wa_c TO gt_c. 56 CLEAR wa_c. 57 ENDLOOP. 58 ENDLOOP. 59 GET RUN TIME FIELD DATA(time2). 60 lv_t = time2 - time1. 61 WRITE:/'未经优化,5000条数据执行时间:',lv_t,'微秒'. 62 ENDFORM.
执行结果:

优化方法1:排序表优化
定义一个排序表并赋值给它,使用排序表进行LOOP循环。
1 FORM frm_loop_sort. 2 GET RUN TIME FIELD DATA(time1). 3 DATA:gt_b_sort TYPE SORTED TABLE OF ty_b WITH NON-UNIQUE KEY col1. 4 SORT gt_b BY col1. 5 gt_b_sort[] = gt_b[]. 6 LOOP AT gt_a INTO wa_a. 7 LOOP AT gt_b_sort INTO wa_b WHERE col1 = wa_a-col1. 8 wa_c-col1 = wa_a-col1. 9 wa_c-col2 = wa_a-col2. 10 wa_c-col3 = wa_b-col3. 11 APPEND wa_c TO gt_c. 12 CLEAR wa_c. 13 ENDLOOP. 14 ENDLOOP. 15 REFRESH gt_c. 16 GET RUN TIME FIELD DATA(time2). 17 lv_t = time2 - time1. 18 WRITE:/'经排序表优化,5000条数据执行时间:',lv_t,'微秒'. 19 ENDFORM.
执行结果:

优化方法2:内表排序INDEX优化
对标准表进行排序并使用INDEX方式进行优化,此方法使用有局限性,要求gt_a-col1不能重复,一旦重复,结果就不对了。
1 FORM frm_sort_index. 2 GET RUN TIME FIELD DATA(time1). 3 DATA:i TYPE i. 4 SORT:gt_a BY col1, 5 gt_b BY col1. 6 i = 1. 7 LOOP AT gt_a INTO wa_a. 8 LOOP AT gt_b INTO wa_b FROM i. 9 IF wa_a-col1 <> wa_b-col1. 10 i = sy-tabix. 11 EXIT. 12 ENDIF. 13 wa_c-col1 = wa_a-col1. 14 wa_c-col2 = wa_a-col2. 15 wa_c-col3 = wa_b-col3. 16 APPEND wa_c TO gt_c. 17 CLEAR wa_c. 18 ENDLOOP. 19 ENDLOOP. 20 REFRESH gt_c. 21 GET RUN TIME FIELD DATA(time2). 22 lv_t = time2 - time1. 23 WRITE:/'经内表排序INDEX优化,5000条数据执行时间:',lv_t,'微秒'. 24 ENDFORM.
执行结果:

暂时先写这两种优化方法,其它方法后面再继续加。
完整代码:
1 REPORT test_loop. 2 3 TYPES:BEGIN OF ty_a, 4 col1(10), 5 col2(10), 6 END OF ty_a, 7 BEGIN OF ty_b, 8 col1(10), 9 col3(10), 10 END OF ty_b, 11 BEGIN OF ty_c, 12 col1(10), 13 col2(10), 14 col3(10), 15 END OF ty_c. 16 17 DATA:wa_a TYPE ty_a, 18 wa_b TYPE ty_b, 19 wa_c TYPE ty_c, 20 gt_a TYPE TABLE OF ty_a, 21 gt_b TYPE TABLE OF ty_b, 22 gt_c TYPE TABLE OF ty_c, 23 lv_t TYPE i. 24 25 START-OF-SELECTION. 26 27 PERFORM frm_getdata. 28 PERFORM frm_loop. 29 PERFORM frm_loop_sort. 30 PERFORM frm_sort_index. 31 PERFORM frm_hs_group. 32 33 34 FORM frm_getdata. 35 DATA lv_line(5) TYPE n. 36 37 DO 5000 TIMES. 38 lv_line = sy-index. 39 40 CLEAR wa_a. 41 wa_a-col1 = 'col1'&& lv_line. 42 wa_a-col2 = 'col2'&& lv_line. 43 APPEND wa_a TO gt_a. 44 45 CLEAR wa_b. 46 wa_b-col1 = wa_a-col1. 47 wa_b-col3 = 'col3'&& lv_line. 48 APPEND wa_b TO gt_b. 49 ENDDO. 50 ENDFORM. 51 52 FORM frm_loop. 53 GET RUN TIME FIELD DATA(time1). 54 LOOP AT gt_a INTO wa_a. 55 LOOP AT gt_b INTO wa_b WHERE col1 = wa_a-col1. 56 wa_c-col1 = wa_a-col1. 57 wa_c-col2 = wa_a-col2. 58 wa_c-col3 = wa_b-col3. 59 APPEND wa_c TO gt_c. 60 CLEAR wa_c. 61 ENDLOOP. 62 ENDLOOP. 63 REFRESH gt_c. 64 GET RUN TIME FIELD DATA(time2). 65 lv_t = time2 - time1. 66 WRITE:/'未经优化,5000条数据执行时间:',lv_t,'微秒'. 67 ENDFORM. 68 69 FORM frm_loop_sort. 70 GET RUN TIME FIELD DATA(time1). 71 DATA:gt_b_sort TYPE SORTED TABLE OF ty_b WITH NON-UNIQUE KEY col1. 72 SORT gt_b BY col1. 73 gt_b_sort[] = gt_b[]. 74 LOOP AT gt_a INTO wa_a. 75 LOOP AT gt_b_sort INTO wa_b WHERE col1 = wa_a-col1. 76 wa_c-col1 = wa_a-col1. 77 wa_c-col2 = wa_a-col2. 78 wa_c-col3 = wa_b-col3. 79 APPEND wa_c TO gt_c. 80 CLEAR wa_c. 81 ENDLOOP. 82 ENDLOOP. 83 REFRESH gt_c. 84 GET RUN TIME FIELD DATA(time2). 85 lv_t = time2 - time1. 86 WRITE:/'经排序表优化,5000条数据执行时间:',lv_t,'微秒'. 87 ENDFORM. 88 89 FORM frm_sort_index. 90 GET RUN TIME FIELD DATA(time1). 91 SORT:gt_a BY col1, 92 gt_b BY col1. 93 LOOP AT gt_a INTO wa_a. 94 LOOP AT gt_b INTO wa_b FROM sy-tabix. 95 IF wa_a-col1 <> wa_b-col1. 96 EXIT. 97 ENDIF. 98 wa_c-col1 = wa_a-col1. 99 wa_c-col2 = wa_a-col2. 100 wa_c-col3 = wa_b-col3. 101 APPEND wa_c TO gt_c. 102 CLEAR wa_c. 103 ENDLOOP. 104 ENDLOOP. 105 REFRESH gt_c. 106 GET RUN TIME FIELD DATA(time2). 107 lv_t = time2 - time1. 108 WRITE:/'经内表排序INDEX优化,5000条数据执行时间:',lv_t,'微秒'. 109 ENDFORM.

浙公网安备 33010602011771号