循环调用PT_ARQ_REQLIST_GET性能低下问题求助
性能优化方案及替代解决方案
问题根源
现有代码通过循环逐个调用PT_ARQ_REQLIST_GET,每个调用都独立执行数据库查询、权限校验、业务逻辑计算,多次调用的开销(如数据库连接、上下文切换)叠加,导致耗时随员工数量增长呈非线性上升,最终触发超时。
一、批量处理替代单员工循环
1. 优先使用批量函数模块
SAP部分HR函数提供批量版本,可通过SE37搜索PT_ARQ*关键词,确认是否存在如PT_ARQ_REQLIST_BULK_GET这类支持批量传入PERNR范围的函数。若存在,直接传入PERNR集合参数,一次性获取所有员工的请求数据,彻底避免循环调用的开销。
2. 利用组织单元批量获取
若目标员工属于同一组织单元(部门、成本中心等),可设置IM_TEAM参数为对应组织的HROBJECT对象,函数会一次性返回该组织下所有员工的请求,无需循环单个PERNR。示例代码修改:
START-OF-SELECTION. * 示例:指定组织单元类型为O,编号为1000 IM_TEAM-TYPE = 'O'. IM_TEAM-OBJID = '1000'. CALL FUNCTION 'PT_ARQ_REQLIST_GET' EXPORTING IM_TEAM = IM_TEAM IM_COMMAND = 'SHOW_REQLIST' IM_MODUS = 'A' IM_DEBUG = ABAP_FALSE " 禁用调试模式 IMPORTING EX_REQUEST_LIST = REQ_LIST EX_AS_OF_DATE = EX_AS_OF_DATE TABLES EX_MESSAGES = MESSAGES EX_COMMANDS = EX_COMMANDS. * 统一处理所有员工的请求数据 LOOP AT REQ_LIST INTO REQ_WA. WRITE: / REQ_WA-PERNR, REQ_WA-REQ_TYPE, REQ_WA-START_DATE. ENDLOOP.
二、优化循环内资源占用
若必须保留循环调用,可通过减少内存冗余提升性能:
- 每次调用后清空临时表:函数返回的
EX_MESSAGES、EX_COMMANDS会累积数据,需在每次循环前清空,避免内存持续膨胀:
LOOP AT XCode1. CLEAR: MESSAGES, EX_COMMANDS, REQ_LIST. " 清空临时存储表 CALL FUNCTION 'PT_ARQ_REQLIST_GET' EXPORTING IM_PERNR = XCode1-LOW IM_TEAM = IM_TEAM IM_COMMAND = 'SHOW_REQLIST' IM_MODUS = 'A' IM_DEBUG = ABAP_FALSE IMPORTING EX_REQUEST_LIST = REQ_LIST EX_AS_OF_DATE = EX_AS_OF_DATE TABLES EX_MESSAGES = MESSAGES EX_COMMANDS = EX_COMMANDS. " 数据处理逻辑... ENDLOOP.
- 禁用调试模式:确保
IM_DEBUG设为ABAP_FALSE,避免函数执行额外的调试日志输出。
三、并行处理拆分任务
将员工列表拆分为多个子集,通过并行任务同时调用函数,利用多进程缩短总耗时。示例实现:
DATA: gt_pernr TYPE TABLE OF pernr-pernr, gv_task_count TYPE i VALUE 0, gv_batch_size TYPE i VALUE 100. " 每批处理100名员工 * 将选择选项转换为PERNR内表 SELECT pernr FROM pernr INTO TABLE gt_pernr WHERE pernr IN XCode1. * 拆分批次并启动并行任务 DO. DATA(lt_batch) = VALUE #( FOR i = gv_task_count * gv_batch_size + 1 TO MIN( (gv_task_count + 1) * gv_batch_size, lines(gt_pernr) ) ( gt_pernr[i] ) ). IF lines(lt_batch) = 0. EXIT. ENDIF. gv_task_count = gv_task_count + 1. CALL FUNCTION 'Z_PT_ARQ_BATCH_GET' " 自定义包装函数,处理单批次PERNR STARTING NEW TASK |TASK_{gv_task_count}| PERFORMING on_batch_finished ENDING ON END_OF_TASK EXPORTING it_pernr = lt_batch. ENDDO. * 等待所有并行任务完成 WAIT UNTIL gv_task_count = 0. * 并行任务完成回调函数 FORM on_batch_finished USING taskname TYPE c LENGTH 8. RECEIVE RESULTS FROM FUNCTION 'Z_PT_ARQ_BATCH_GET' IMPORTING et_req_list = DATA(lt_result). " 合并批次结果到全局表 APPEND LINES OF lt_result TO REQ_LIST. gv_task_count = gv_task_count - 1. ENDFORM.
注:需自定义Z_PT_ARQ_BATCH_GET函数,内部循环批次内的PERNR调用原函数并收集结果。
四、直接查询底层数据库表
若业务逻辑允许(无需复杂权限校验或函数内的状态转换),直接查询请假请求的底层表是性能最优方案。示例:
DATA: gt_ptreq_header TYPE TABLE OF ptreq_header, gt_ptreq_detail TYPE TABLE OF ptreq_detail. * 批量获取请求表头 SELECT * FROM ptreq_header INTO TABLE gt_ptreq_header WHERE pernr IN XCode1. * 批量获取请求明细 SELECT * FROM ptreq_detail INTO TABLE gt_ptreq_detail WHERE req_id IN ( SELECT req_id FROM ptreq_header WHERE pernr IN XCode1 ). * 关联表头与明细处理数据 LOOP AT gt_ptreq_header INTO DATA(wa_header). DATA(lt_detail) = VALUE #( FOR wa_detail IN gt_ptreq_detail WHERE ( req_id = wa_header-req_id ) ( wa_detail ) ). WRITE: / wa_header-pernr, wa_header-req_type, wa_header-start_date. ENDLOOP.
注意:需确保查询逻辑与PT_ARQ_REQLIST_GET的过滤条件、权限规则一致,避免数据遗漏或不符合业务要求。
五、其他优化建议
- 添加数据库索引:若直接查询表,确保
PERNR、REQ_ID等核心字段有合适的索引,提升查询速度。 - 减少实时输出:原代码中的
WRITE语句会增加IO开销,可先将数据存入内表,循环结束后统一输出。
内容的提问来源于stack exchange,提问作者Ehab
相关产品推荐
相关产品推荐

