You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 16:27:51