双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.
View Code

 

执行结果:

 

 

 

 

优化方法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.
View Code

 

执行结果:

 

 

优化方法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.
View Code

 

执行结果:

 

 

暂时先写这两种优化方法,其它方法后面再继续加。

 

完整代码:

  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.
View Code

 

posted @ 2021-06-24 14:30  LouiseMa  阅读(364)  评论(0)    收藏  举报