SAP 提供多种多线程的方法去优化程序的执行效率
1.分别执行多个job
2.Call function STARTING NEW TASK
3.直接使用SAP 提供的SPTA 框架函数:SPTA_PARA_PROCESS_START_2
本次,我们着重来介绍一下三种方法中函数的使用方法
获取空闲线程数:SPBT_INITIALIZE
*&---------------------------------------------------------------------*
*& Report ZDEMO_TEST_PARALLEL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdemo_test_parallel.
TYPE-POOLS:spta.
DATA: gs_head TYPE zsfi_doc_head.
DATA: gt_head TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: gt_out TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: gt_item TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: gs_item TYPE zsfi_doc_item.
DATA: ls_head TYPE zsfi_doc_head.
DATA: lt_head TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: lt_item TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: ls_item TYPE zsfi_doc_item.
DATA: lv_int TYPE numc4.
DATA: gs_parallel TYPE zsfi_doc_head_run.
DATA: gt_parallel TYPE ztfi_doc_head_run_t.
DATA: gt_result TYPE ztfi_doc_head_run_t.
DATA: gv_start TYPE char10.
DATA: gv_end TYPE char10.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-t01.
PARAMETERS: p_group TYPE spta_rfcgr OBLIGATORY MEMORY ID spta_rfcgr DEFAULT 'parallel_generators'.
PARAMETERS: p_task LIKE sy-index DEFAULT '10'.
PARAMETERS: p_times TYPE numc4 OBLIGATORY DEFAULT '100'.
PARAMETERS: p_loop TYPE char01 RADIOBUTTON GROUP rd1 DEFAULT 'X'.
PARAMETERS: p_para TYPE char01 RADIOBUTTON GROUP rd1 .
SELECTION-SCREEN END OF BLOCK b1.
START-OF-SELECTION.
lv_int = p_times.
SELECT SINGLE *
INTO CORRESPONDING FIELDS OF ls_head
FROM ztfi_doc_head
WHERE zsernr = 'BPM26020240606000003'.
SELECT *
INTO CORRESPONDING FIELDS OF TABLE lt_item
FROM ztfi_doc_item
WHERE zsernr = 'BPM26020240606000003'.
CASE 'X'.
WHEN p_loop.
PERFORM frm_loop_process.
WHEN p_para.
PERFORM frm_parallel_process.
WHEN OTHERS.
ENDCASE.
*&---------------------------------------------------------------------*
*& Form FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM frm_loop_process .
DATA: lv_errcode TYPE char8.
DATA: lv_errdesc TYPE char250.
gv_start = sy-uzeit.
IF ls_head IS NOT INITIAL AND lt_item IS NOT INITIAL .
DO p_times TIMES.
lv_int = lv_int - 1.
CLEAR:lv_errcode,lv_errdesc,gt_item,gt_head,gt_out.
CONCATENATE 'BPM06020240612LOOP9' lv_int INTO ls_head-zsernr.
CONCATENATE '240606LOOP4' lv_int INTO ls_head-orderid.
APPEND ls_head TO gt_head.
LOOP AT lt_item INTO ls_item .
CONCATENATE 'BPM06020240612LOOP9' lv_int INTO ls_item-zsernr.
APPEND ls_item TO gt_item.
ENDLOOP.
CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'
IMPORTING
errcode = lv_errcode
errdesc = lv_errdesc
TABLES
it_head = gt_head
it_item = gt_item
ot_head = gt_out.
ENDDO.
ENDIF.
gv_end = sy-uzeit.
WRITE gv_start.
WRITE gv_end.
ENDFORM. " FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
*& Form FRM_PARALLEL_PROCESS
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM frm_parallel_process .
CLEAR:gt_parallel.
DO p_times TIMES.
lv_int = lv_int + 1.
CLEAR:gt_item,gt_head,gs_parallel.
CONCATENATE 'BPM06020240612PARALLEL9' lv_int INTO ls_head-zsernr.
CONCATENATE '240612PARAL9' lv_int INTO ls_head-orderid.
MOVE-CORRESPONDING ls_head TO gs_parallel.
LOOP AT lt_item INTO ls_item .
CONCATENATE 'BPM06020240612PARALLEL9' lv_int INTO ls_item-zsernr.
APPEND ls_item TO gt_item.
ENDLOOP.
gs_parallel-item = gt_item.
APPEND gs_parallel TO gt_parallel.
ENDDO.
gv_start = sy-uzeit.
CALL FUNCTION 'SPTA_PARA_PROCESS_START_2'
EXPORTING
server_group = p_group
max_no_of_tasks = p_task
before_rfc_callback_form = 'BEFORE_RFC'
in_rfc_callback_form = 'IN_RFC'
after_rfc_callback_form = 'AFTER_RFC'
callback_prog = sy-repid
CHANGING
user_param = gt_parallel "this is for you to transfer data you want to deal
EXCEPTIONS
invalid_server_group = 1
no_resources_available = 2
OTHERS = 3.
gv_end = sy-uzeit.
WRITE gv_start.
WRITE gv_end.
ENDFORM. " FRM_PARALLEL_PROCESS
*&---------------------------------------------------------------------*
*& Form before_rfc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IS_BEFORE_RFC_IMP text
* -->CS_BEFORE_RFC_EXP text
* -->CT_RFCDATA text
* -->CT_FAILED_OBJECTS text
* -->CT_OBJECTS_IN_PROCESS text
* -->P_USER_PARAM text
*----------------------------------------------------------------------*
FORM before_rfc USING is_before_rfc_imp TYPE spta_t_before_rfc_imp
CHANGING
cs_before_rfc_exp TYPE spta_t_before_rfc_exp
ct_rfcdata TYPE spta_t_indxtab
ct_failed_objects TYPE spta_t_failed_objects
ct_objects_in_process TYPE spta_t_objects_in_process
ct_user_param TYPE ztfi_doc_head_run_t. " you own data
DATA: ls_parallel TYPE zsfi_doc_head_run.
DATA: lt_parallel TYPE STANDARD TABLE OF zsfi_doc_head_run.
DATA: lv_counter TYPE i.
DATA: lv_package TYPE i.
* define the package size as 10
lv_package = 10.
CLEAR:lt_parallel.
LOOP AT ct_user_param INTO gs_parallel.
IF lv_counter < lv_package.
APPEND gs_parallel TO lt_parallel.
DELETE ct_user_param INDEX 1.
lv_counter = lv_counter + 1.
ELSE.
EXIT.
ENDIF.
ENDLOOP.
* Convert the input data into the INDX structure that is needed for the RFC
CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
EXPORTING
data = lt_parallel
IMPORTING
indxtab = ct_rfcdata.
IF lt_parallel IS INITIAL.
CLEAR cs_before_rfc_exp-start_rfc.
EXIT.
ELSE.
* Inform task manager that an RFC can be started from the
* data compiled
cs_before_rfc_exp-start_rfc = 'X'.
ENDIF.
ENDFORM. "before_rfc
*&---------------------------------------------------------------------*
*& Form in_rfc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IS_IN_RFC_IMP text
* -->ES_IN_RFC_EXP text
* -->IT_RFCDATA text
*----------------------------------------------------------------------*
FORM in_rfc
USING is_in_rfc_imp TYPE spta_t_in_rfc_imp
CHANGING es_in_rfc_exp TYPE spta_t_in_rfc_exp
ct_rfcdata TYPE spta_t_indxtab.
DATA: ls_head_temp TYPE zsfi_doc_head.
DATA: lt_head_temp TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: lt_out_temp TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: lt_item_temp TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: ls_parallel TYPE zsfi_doc_head_run.
DATA: lt_parallel TYPE STANDARD TABLE OF zsfi_doc_head_run.
DATA: gt_out_temp TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: lv_errcode TYPE char8.
DATA: lv_errdesc TYPE char250.
* decode the data from the INDX Structure into the process work list
CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
EXPORTING
indxtab = ct_rfcdata
IMPORTING
data = lt_parallel.
*you own process logic
LOOP AT lt_parallel INTO ls_parallel.
CLEAR:lv_errcode,lv_errdesc,lt_item_temp,lt_head_temp,lt_out_temp.
MOVE-CORRESPONDING ls_parallel TO ls_head_temp.
APPEND ls_head_temp TO lt_head_temp.
lt_item_temp = ls_parallel-item.
CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'
IMPORTING
errcode = lv_errcode
errdesc = lv_errdesc
TABLES
it_head = lt_head_temp
it_item = lt_item_temp
ot_head = lt_out_temp.
APPEND LINES OF lt_out_temp TO gt_out_temp.
ENDLOOP.
* repack output data for AFTER_RFC form
CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
EXPORTING
data = lt_parallel
IMPORTING
indxtab = ct_rfcdata.
COMMIT WORK.
ENDFORM. "in_rfc
*&---------------------------------------------------------------------*
*& Form after_rfc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IT_RFCDATA text
* -->IF_RFCSUBRC text
* -->IF_RFCMSG text
* -->IT_OBJECTS_IN_PROCESS text
* -->IS_AFTER_RFC_IMP text
* -->ES_AFTER_RFC_EXP text
* -->CS_USER_PARAM text
*----------------------------------------------------------------------*
FORM after_rfc USING it_rfcdata TYPE spta_t_indxtab
if_rfcsubrc TYPE sy-subrc
if_rfcmsg TYPE spta_t_rfcmsg
it_objects_in_process TYPE spta_t_objects_in_process
is_after_rfc_imp TYPE spta_t_after_rfc_imp
CHANGING es_after_rfc_exp TYPE spta_t_after_rfc_exp
cs_user_param .
DATA: lt_out TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: lt_parallel TYPE STANDARD TABLE OF zsfi_doc_head_run.
* uppack RFC output data and add RFC reulsts to global data
CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
EXPORTING
indxtab = it_rfcdata
IMPORTING
data = lt_parallel.
APPEND LINES OF lt_parallel TO gt_result.
ENDFORM. "after_rfc
上面的demo 我分别使用loop和parallel (10线程)去创建会计凭证
创建1000条,运行时间分别为:95 sec 17 sec
如此一比较下来。多线程的效率提升还是很快的。对于没有升级到HANA的ECC 系统还是有很多提升空间的