Recently I am responsible for the performance optimization of one API which retrieves application logs of the given one order documents.
API Requirement
The input is an internal table containing document guids, and output are all the application logs belonging to those documents, with type “Error” and priority “Very important” and “Important”.
For the application logs of a single document, you can view them via tcode SLG1 as below:
The application logs would be displayed in WebUI as below:
The signature of API:
The structure of table type CRMT_ODATA_TASK_LOGST could be found below:
Original implementation ( has performance issue )
The idea of original implementation is:
LOOP AT it_order_guid_tab.
" get all of the message handles of the current order by its guid and stores to variable lt_message_handles
LOOP AT lt_message_handles.
" get the detail of each message according to its handle
ENDLOOP.
ENDLOOP.
As you see there are nested loop, so the algorithm complexity is o(n2).
The optimized implementation
The idea is to avoid the nested LOOP.
" get all message handles belonging to all orders in a single method call
lt_all_message_handlers = get_all( it_order_guid_tab ).
LOOP AT lt_all_message_handlers.
" get the detail of each message according to its handle
ENDLOOP.
The algorithm complexity is reduced to o(n). The original implementation could be found from method GET_ORDER_ERROR_MESSAGE of the class CL_CRM_ORDER_MESSAGE_TOOL in the attachment. The optimized version is in method GET_ORDER_ERROR_MESSAGE_OPT.
Performance comparison
I do the performance measurement based on the following three scenarios. We can see the performance is improved a lot after nested LOOP is removed.
The idea of original implementation is:
Unit Test
In order to guarantee that the optimized implementation does return exactly the same data as the original one, I write the following report to do unit test. The design is quite simple, retrieve the application log for the same input twice, one using the original implementation and the other one using the optimized version, and eASSERT lt_result1 = lt_result2. The report source code is attached here:
REPORT tool_display_log_compare.
CLASS lcl_test DEFINITION.
PUBLIC SECTION.
METHODS: test_all_oppt, test_created_by_jerry, test_oppt_jerry,
constructor.
PRIVATE SECTION.
METHODS: get_oppt_guid, compare, get_created_by, get_oppt_jerry.
DATA: mt_guid_tab TYPE crmt_object_guid_tab,
mt_msg_origin TYPE crmt_odata_task_logst,
mt_msg_opt LIKE mt_msg_origin,
mo_tool TYPE REF TO cl_crm_order_message_tool.
ENDCLASS.
CLASS lcl_test IMPLEMENTATION.
METHOD: test_oppt_jerry.
get_oppt_jerry( ).
compare( ).
WRITE: / 'lines of message: ' , lines( mt_msg_origin ).
WRITE: / 'test on all Opportunity with type OPPT and created by Jerry passed.' COLOR COL_NEGATIVE.
ENDMETHOD.
METHOD: test_created_by_jerry.
get_created_by( ).
compare( ).
WRITE: / 'lines of message: ' , lines( mt_msg_origin ).
WRITE: / 'test on all Opportunity created by Jerry passed.' COLOR COL_NEGATIVE.
ENDMETHOD.
METHOD: test_all_oppt.
get_oppt_guid( ).
compare( ).
WRITE: / 'lines of message: ' , lines( mt_msg_origin ).
WRITE: / 'test on all Opportunity with type OPPT passed.' COLOR COL_NEGATIVE.
ENDMETHOD.
METHOD: get_created_by.
CLEAR: mt_guid_tab.
SELECT guid INTO TABLE mt_guid_tab FROM crmd_orderadm_h WHERE created_by = 'WANGJER'.
ENDMETHOD.
METHOD: get_oppt_jerry.
CLEAR: mt_guid_tab.
SELECT guid INTO TABLE mt_guid_tab FROM crmd_orderadm_h WHERE process_type = 'OPPT' AND created_by = 'WANGJER'.
ENDMETHOD.
METHOD: get_oppt_guid.
CLEAR: mt_guid_tab.
SELECT guid INTO TABLE mt_guid_tab FROM crmd_orderadm_h WHERE process_type = 'OPPT'.
ENDMETHOD.
METHOD: compare.
CLEAR: mt_msg_origin, mt_msg_opt.
mt_msg_origin = mo_tool->get_order_error_message_opt( mt_guid_tab ).
CALL FUNCTION 'CRM_MESSAGES_INIT'
EXPORTING
it_docnumber = mt_guid_tab.
mt_msg_opt = mo_tool->get_order_error_message( mt_guid_tab ).
SORT mt_msg_origin BY header_guid log_msg.
SORT mt_msg_opt BY header_guid log_msg.
ASSERT mt_msg_origin = mt_msg_opt.
ENDMETHOD.
METHOD: constructor.
mo_tool = NEW cl_crm_order_message_tool( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA: lo_test TYPE REF TO lcl_test.
lo_test = new lcl_test( ).
lo_test->test_all_oppt( ).
lo_test->test_created_by_jerry( ).
lo_test->test_oppt_jerry( ).
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关推荐
SAP CRM(Customer Relationship Management)是一款由SAP公司推出的企业级软件,主要用于优化企业的客户关系管理过程。与SAP ECC(Enterprise Core Component)和SAP BW(Business Warehouse)一样,SAP CRM 是一个...
SAP CRM (Customer Relationship Management) 是一个全面的解决方案,旨在帮助企业管理和优化与客户之间的互动过程。IPC(Interactive Pricing Component)作为SAP CRM中的一个重要组成部分,主要用于处理业务交易中...
在IT行业中,SAP Business One是一款专为中小型企业设计的集成化管理软件,它涵盖了财务管理、销售与分销、生产计划等多个业务领域。SAP Business One的二次开发是针对这款软件的功能扩展和定制化需求,以满足企业的...
《SAP Business One 10.0版本二次开发与Java环境下的应用详解》 SAP Business One是一款由SAP公司推出的中小企业管理软件,它涵盖了财务管理、销售与分销、生产计划等多个核心业务领域,帮助企业实现全面的业务流程...
Excel 宏读取 SAP 数据方法详解 Excel 宏读取 SAP 数据方法是指使用 Excel 宏从 SAP 系统中读取数据。这种方法可以实现直接从 Excel 输出报表数据的关键是sap Web Services。下面是该方法的详细介绍。 首先,需要...
4. 错误处理和日志记录:提供统一的错误处理机制,以及方便的日志记录功能,帮助开发者调试和优化应用。 5. 示例代码和文档:可能包含了使用该客户端的示例代码,以及详细的API文档,帮助开发者快速上手。 至于...
标题"SAP读取Access数据"涉及的是在SAP系统中如何与Microsoft Access数据库进行交互,以便获取、处理或更新Access数据库中的数据。这篇博客文章可能提供了实现这一目标的代码示例和技术指南。以下是对这个主题的详细...
通过各种内置工具和编程接口,我们可以高效地获取和分析这些日志数据,从而优化系统性能和保障系统安全。在实际工作中,掌握日志管理技能不仅可以提高工作效率,也是提升系统管理能力的关键一步。
在Kettle中,你可以执行各种操作,如读取SAP表数据、调用RFC(远程功能调用)、执行BAPI(Business Application Programming Interface)函数等。这些操作可以通过SAP的Step进行,例如SAP Get Table、SAP Call RFC或...
通过ABAP程序读取SAP中生成的请求号
综上所述,朗阁教育集团通过应用SAP Business ByDesign解决方案,成功地解决了对销售和CRM数据实时分析的需求,实现了业务流程的优化和管理效率的提升,为企业的持续发展和市场竞争提供了坚实的技术支持。
RFC是SAP NetWeaver平台的一部分,它提供了标准化的接口,使得外部应用程序(如Java、Python或其他非SAP系统)可以调用SAP系统的业务逻辑。这些调用通常涉及到事务处理、数据查询或执行特定的业务流程。 在SAP ABAP...
在软件开发中,.Net 调用 SAP RFC 接口来读取数据是一种常见的应用场景。本文将详细介绍如何使用 .Net 框架调用 SAP RFC 接口来读取数据,并记录了调试的全过程。 关键前提 在开始编程之前,需要满足以下几个关键...
它作为桥梁,使得.NET开发人员能够轻松访问SAP业务功能,如读取数据、执行事务处理或调用SAP Business Objects等功能。SNC支持多种通信协议,包括HTTP/HTTPS、SOAP、XML、RFC等,提供了丰富的API接口,使得开发者...
- 在企业级应用集成中,SAP NetWeaver RFC SDK常被用于构建与SAP系统的桥梁,实现与其他ERP、CRM或其他业务系统的数据交换。例如,通过SDK,Java或.NET开发人员可以轻松地在非SAP环境中调用SAP的BAPIs(Business ...
SAP 方丈是一种基于 ABAP 的编程语言,用于开发 SAP 系统中的应用程序。ABAP 语言是 SAP 公司开发的一种高级编程语言,用于开发 SAP 系统中的应用程序。通过 ABAP 语言,可以对 SAP 系统中的数据进行操作、处理和...
2. **SAP Gateway集成**:支持与SAP Gateway进行通信,利用OData服务访问SAP数据,使.NET应用能够轻松地实现对SAP系统的CRUD(创建、读取、更新、删除)操作。 3. **SAP Business Object Repository(BOR)访问**:...
文本文件记录日志的简单实用的日志类, ... 3)可以指定保持日志文件文件夹,如果不指定日志文件夹,Web应用保持到Bin文件夹,Windows Forms应用保持到.EXE文件所在的文件夹。 4)可以指定日志文件的前缀。