在SAP的应用开发中,对于报表的效率是非常重视的。当然优化报表效率的方法有很多,当时当我们遇到需要处理大量数据的报表时会发现用尽所有优化的语句,报表的运行效率还是无法达到用户部门的需求。
下面,我介绍一种方法,也许会对你有所帮助。ABAP的
并行处理(原理类似于java的多线程),它是通过RFC接口进行远程函数的异步调用实现程序的并处理。
同步/异步调用函数语法:
同步(sRFC): CALL FUNCTION 'AAA' ;
同步调用的实质:程序进行单线程执行;
异步(aRFC): CALL FUNCTION 'AAA' STARTING NEWTASK <taskname>
"任务名称
DESTINATION IN GROUP <RFC Serve Group>
PERFORMING <subroutine> ON END OF TASK 。
"子程序
异步调用的实质:程序进行多线程执行;
在使用并行处理的过程中通常会遇到如下的可能会发生的
问题:
1、重复运行产生的后台任务相互冲突
2、异步调用获取的最终结果与同步调用结果存在差异
3、固定RFC Server Group如system = 'parallel_generators'
,无法保证程序在不同服务器中通用性。
对上述三个问题的
解决方法,如下:
1、为了避免后台任务相互冲突,导致输出的数据差异,应确保在相同时间段内同一程序只能被一个用户
占用。所以在开发的程序中添加所对象可以解决。(程序锁的设置,如附件)
2、分析:在LOOP循环中采用异步调用函数的模式,通过SY-SUBRC = 0来判断任务启动成功,
当SY-SUBRC <> 0时,则获取先前启动的进程返回的值,但是这样就遇到一个问题:如第N次循环正好
分配给程序的进程被占用完,这样本次无法启动一个任务进程,导致本次的原始数据通过函数无法获取
目标,从而最终结果出现数据不完整和数值不断变化的现象。
解决:牺牲部分性能保证数据的完整。通过RZ12获取服务器的Max. requests in queue 的值,LOOP
循环的时候统计启动的启动的进程数是否 = Max. requests inqueue,如果等于则获取先前启动的进程
返回的值,然后再重新启动进程,重复此操作。系统分配给每个程序的最大进程数> Max. requests in
queue,但是把启动的进程数限制在Max.requests in queue的水平可以保证获取结果的完整性
3、如何知道系统设置的并行运行进程数呢,通过
RZ12,并双击当前登入组,即可以查看到最大并行进程数,
如下图:
一般系统直接指定<RFC Serve Group> =' parallel_generators ',如上图的“服务器组”对应的内容,为了保持一般性通过如下逻辑段获取:
变量定义-
DATA: g_classname
Type rzlli_apcl, "Server Group Name
g_applserver
Type rzllitab-applserver."RFC Serve Group
取数逻辑-
CALL 'C_SAPGPARAM' "#EC CI_CCALL
ID 'NAME' FIELD 'rdisp/myname'
ID 'VALUE' FIELD g_applserver.
ID 'NAME' FIELD 'rdisp/myname'
ID 'VALUE' FIELD g_applserver.
SELECT SINGLE classname
FROM rzllitab
INTO g_classname "Server Group Name
WHERE applserver = g_applserver
AND grouptype = 'S'. "S:服务器组,空:登陆组
通过上述的描述,可以通过一个实例来串联一下,实例如附件。
1、获取服务组
2、异步调用函数
3、处理子例程
4、如果调用的子例程非系统标准,需要在SE37中定义自己需要的处理逻辑子例程
1 *&---------------------------------------------------------------------* 2 *& Report ZPPR0056 3 *&----------------------------------------------------------------------* 4 *& Program Name : ZPPR0056 5 *& Author's Name : QLB 6 *& Written Date : 2014.01.08 7 *& Request Number: DEVK940516 8 *& Program Description: 共用料区分建议报表--并行处理 9 *&----------------------------------------------------------------------* 10 * Changer Changed Date Request NO. Dec. 11 *&----------------------------------------------------------------------* 12 13 report zppr0056 message-id zppmess. 14 15 tables: mara,marc. 16 17 types: begin of gs_out, 18 werks type marc-werks,"工厂 19 dispo type marc-dispo,"MRP控制员 20 matnr type marc-matnr,"物料 21 maktx type makt-maktx,"物料描述 22 meins type mara-meins,"单位 23 matkl type mara-matkl,"物料组 24 labst type mard-labst,"NO-X非限制库存 25 zsupl type mard-labst,"NO-X过期供给 26 zreqd type mard-labst,"NO-X过期需求 27 ztype type c, "期间类型 28 ztext type c length 20,"期间类型文本 29 dat01 type mard-labst, "期间-one 30 dat02 type mard-labst, "期间-two 31 dat03 type mard-labst, "期间-three 32 dat04 type mard-labst, "期间-four 33 dat05 type mard-labst, "期间-five 34 dat06 type mard-labst, "期间-six 35 dat07 type mard-labst, "期间-seven 36 dat08 type mard-labst, "期间-eight 37 dat09 type mard-labst, "期间-nine 38 dat10 type mard-labst, "期间-ten 39 dat11 type mard-labst, "期间-evelen 40 dat12 type mard-labst, "期间-twelve 41 end of gs_out, 42 43 begin of gs_dtl, 44 werks type marc-werks,"工厂 45 matnr type marc-matnr,"物料 46 zdate type sy-datum, "需求日期 47 delb0 type t457t-delb0,"MRP元素 48 extra type mdez-extra,"MRP元素数据 49 mng01 type mdez-mng01,"收货数量或需求数量 50 end of gs_dtl, 51 52 begin of gs_marc, 53 matnr type marc-matnr,"物料ID 54 werks type marc-werks,"工厂 55 dispo type marc-dispo,"MRP控制员 56 matkl type mara-matkl,"物料组 57 meins type mara-meins,"基本单位 58 end of gs_marc, 59 60 begin of gs_mard, 61 matnr type mard-matnr,"物料 62 werks type mard-werks,"工厂 63 lgort type mard-lgort,"库存地点 64 labst type mard-labst,"库存数 65 end of gs_mard, 66 67 begin of gs_makt, 68 matnr type makt-matnr,"物料 69 maktx type makt-maktx,"物料描述 70 end of gs_makt, 71 72 begin of gs_task, 73 matnr type marc-matnr,"物料 74 werks type marc-werks,"工厂 75 dispo type marc-dispo,"MRP控制员 76 matkl type mara-matkl,"物料组 77 meins type mara-meins,"单位 78 maktx type makt-maktx,"物料描述 79 labst type mard-labst,"库存 80 taskname type c length 12, 81 end of gs_task. 82 83 data: gw_task type gs_task, 84 gt_task type standard table of gs_task. 85 86 data: gw_out type gs_out, 87 gw_dtl type gs_dtl, 88 gw_mard type gs_mard. 89 90 data: gt_out type standard table of gs_out, 91 gt_dtl type standard table of gs_dtl,"明细alv 92 gt_marc type standard table of gs_marc, 93 gt_marc_d type standard table of gs_marc, 94 gt_makt type standard table of gs_makt, 95 gt_mard type standard table of gs_mard, 96 gt_mard_s type standard table of gs_mard. 97 data: gt_noxlog type standard table of znoxlog with header line. 98 99 field-symbols:<fs_out> type gs_out, 100 <fs_mard> type gs_mard, 101 <fs_marc> type gs_marc, 102 <fs_makt> type gs_makt, 103 <fs_mrp> type bapi_mrp_items, 104 <fs>, 105 <fs1>, 106 <fs2>, 107 <fs3>. 108 109 data: gt_mrp_items type standard table of bapi_mrp_items."MRP_ITEMs数据 110 111 112 data: g_txt type c length 20, 113 g_num type n length 2. 114 data: g_mondy type d, 115 g_sundy type d. 116 data: g_post type i. 117 data: g_mark type c. 118 119 *****-------GRID_ALV定义 120 class lcl_alv definition deferred. 121 data: g_alv type ref to lcl_alv. 122 data: gt_fcat type lvc_t_fcat, 123 gw_fcat type lvc_s_fcat, 124 is_layo type lvc_s_layo, 125 is_vart type disvariant. 126 data: g_grid1 type ref to cl_gui_alv_grid, 127 g_custom_container1 type ref to cl_gui_custom_container, 128 g_container1 type scrfname value 'GRID_01'. 129 data: ok_code type sy-ucomm, 130 save_ok type sy-ucomm. 131 132 *-----------------------------------------------------------------------* 133 *DESC:异步取数变量定义 134 *-----------------------------------------------------------------------* 135 data: g_taskname(12) type c, "task name(同时运行的任务名称必须保持唯一) 136 g_classname type rzlli_apcl, "Server Group Name 137 g_applserver type rzllitab-applserver."RFC Serve Group 138 139 data: snd_jobs type i, 140 rcv_jobs type i, 141 functioncall1(1) type c. 142 143 constants: done(1) type c value 'X', 144 pnum type i value 5."进程数 145 146 *----------------------------------------------------------------------* 147 * CLASS LCL_ALV DEFINITION 148 *----------------------------------------------------------------------* 149 * 150 *----------------------------------------------------------------------* 151 class lcl_alv definition. 152 public section. 153 methods: 154 create_object, 155 fcat_setting, 156 layo_setting, 157 disp, 158 main. 159 160 private section. 161 162 endclass. "LCL_ALV DEFINITION 163 164 *----------------------------------------------------------------------* 165 * CLASS LCL_ALV IMPLEMENTATION 166 *----------------------------------------------------------------------* 167 * 168 *----------------------------------------------------------------------* 169 class lcl_alv implementation. 170 method create_object. 171 if g_custom_container1 is initial. 172 "创建容器 173 create object g_custom_container1 174 exporting 175 container_name = g_container1 176 exceptions 177 cntl_error = 1 178 cntl_system_error = 2 179 create_error = 3 180 lifetime_error = 4 181 lifetime_dynpro_dynpro_link = 5 182 others = 6. 183 if sy-subrc ne 0. 184 message 'error1' type 'E'. 185 endif. 186 187 "创建ALV 188 create object g_grid1 189 exporting 190 i_parent = g_custom_container1 191 exceptions 192 error_cntl_create = 1 193 error_cntl_init = 2 194 error_cntl_link = 3 195 error_dp_create = 4 196 others = 5. 197 if sy-subrc ne 0. 198 message 'error2' type 'E'. 199 endif. 200 201 else. 202 g_grid1->refresh_table_display( ). 203 endif. 204 205 endmethod. "CREATE_OBJECT 206 207 method fcat_setting. 208 perform frm_set_fcat. 209 210 endmethod. "FCAT_SETTING 211 212 method layo_setting. 213 is_layo-zebra = 'X'."隔行颜色 214 is_layo-sel_mode = 'A'."可选 215 is_layo-cwidth_opt = 'X'."输出列显示最优化 216 217 is_vart-report = sy-repid. 218 endmethod. "LAYO_SETTING 219 220 method disp. 221 "输出ALV 222 call method g_grid1->set_table_for_first_display 223 exporting 224 i_structure_name = 'GS_DTL' 225 is_variant = is_vart 226 i_save = 'A' 227 i_default = 'X' 228 is_layout = is_layo 229 changing 230 it_outtab = gt_dtl[] 231 it_fieldcatalog = gt_fcat[] 232 "it_sort = gt_sort[] 233 exceptions 234 invalid_parameter_combination = 1 235 program_error = 2 236 too_many_lines = 3 237 others = 4. 238 if sy-subrc ne 0. 239 message 'error3' type 'E'. 240 endif. 241 242 call method cl_gui_control=>set_focus 243 exporting 244 control = g_grid1. 245 endmethod. "DISP 246 247 method main. 248 me->create_object( ). 249 me->fcat_setting( ). 250 me->layo_setting( ). 251 me->disp( ). 252 endmethod. "MAIN 253 254 endclass. "LCL_ALV IMPLEMENTATION 255 256 *---------------------------------------------------------------------* 257 * DESC:ALV 变量定义 258 *---------------------------------------------------------------------* 259 type-pools: slis. 260 data: gt_fieldcat type slis_t_fieldcat_alv with header line, "定义存放输出字段的内表 261 gt_sort type slis_t_sortinfo_alv, 262 gw_layout type slis_layout_alv, "定义ALV布局设置的工作区 263 g_repid like sy-repid. "定义系统当前程序名变量 264 data: gw_stru_disvar type disvariant, "ALV 显示格式 265 gt_events type slis_t_event. "ALV 事件 266 267 *-----------------------------------------------------------------------* 268 *DESC:选择屏幕定义 269 *-----------------------------------------------------------------------* 270 selection-screen begin of block blk with frame title text-001. 271 select-options:s_werks for marc-werks obligatory,"工厂 272 s_matnr for marc-matnr,"物料 273 s_dispo for marc-dispo obligatory,"MRP控制员 274 s_matkl for mara-matkl."物料组 275 select-options:s_lgort for marc-lgpro no-display."NO-X库存 276 parameters: p_date type mara-ersda default sy-datum obligatory."开始日期 277 selection-screen end of block blk. 278 279 *-----------------------------------------------------------------------* 280 *INITIALIZATION 281 *-----------------------------------------------------------------------* 282 initialization. 283 perform frm_init. 284 285 *-----------------------------------------------------------------------* 286 *START-OF-SELECTION 287 *-----------------------------------------------------------------------* 288 start-of-selection. 289 perform frm_status(zpercent) using 10 '正在读取其他关联数据...'. 290 perform frm_get_date."获取计算期间的起始值 291 perform frm_get_data."获取基本数据 292 if g_mark eq 'X'. 293 stop. 294 else. 295 perform frm_set_lock."设置锁 296 perform frm_fill_alv. 297 perform frm_set_unlock."解锁 298 perform frm_get_event. 299 perform frm_init_layout. 300 perform frm_sort_build changing gt_sort. 301 perform frm_fcat_setting. 302 perform frm_output tables gt_out. 303 endif. 304 305 306 *&---------------------------------------------------------------------* 30