二维码

[性能] 优化ABAP程序性能的综合方法

Twilight发表于 2014-02-09 19:15qshiou 最后回复于 2015-07-22 11:48 [复制链接] 3729 3

ABAP程序很关注性能问题。但是在程序初期,由于没有大量的测试数据,我们很难发现一些程序的性能瓶颈在哪里,更无从谈如何优化性能了。不过,我想,如果在开发早期遵循一些好的开发方法,就有可能避免后期程序发生大的性能问题。

一、影响 ABAP 程序性能的因素
影响ABAP程序性能的因素有很多,了解这些因素能够帮助我们分析ABAP程序运行异常缓慢的原因。
  • 硬件性能
    数据库服务器、应用服务器的处理能力,客户端电脑的性能等都会影响ABAP程序的性能。
  • 网络带宽
    ABAP 程序需要在在服务器之间、服务器与客户端之间传递数据,网络吞吐量的高低直接影响程序的性能。
  • 服务器不合理的配置
    SAP 服务器不合理的配置,特别是内存的配置,影响 ABAP 程序的性能。
  • 数据库表不合理的索引
    数据库表索引能够提高查询数据的速度,但同时也会增加服务器选择索引的成本和更新索引的开销。因此,没有索引和滥建索引都会影响 ABAP 程序的性能。
  • 程序处理的数据量
    如果随着数据量的增加,程序的执行时间呈对数方式提升,则说明程序的性能较好,如果呈指数方式上升,则程序性能很差。
  • 程序不合理的代码
    不合理的 ABAP 程序代码也会影响程序执行的性能。

二、优化程序性能的基本原则
  • 减少对数据库的访问
    访问数据库消耗非常多的时间,频繁的访问数据库,对程序性能的影响是显而易见的,因为这意味着数据库开销的增加和网络往返次数的增加,所以在一个程序中,访问数据库的次数越少越好。有时宁愿一次多返回一些数据,也不要增加访问次数。
  • 减少网络往返的数据量
    网络传输也能很明显的影响程序的执行时间。如果传输的数据量很大,那么网络延迟的时间就会很明显。
  • 减少循环次数
    循环会增加 CPU 的负载。虽然每次循环执行的时间比较短,但是随着循环次数的增加,累计的处理时间就很长。

三、优化程序性能的方法
1. 确定影响程序性能的主要原因
要解决问题,首先要知道问题出在哪里。因此,寻找影响程序变慢的主要原因非常重要,盲目的进行程序的修改只会使问题变的复杂。

2. 通过内表(Internal Table)处理来减少对数据库的访问
把经常使用的固定大小的数据一次性的读取到Internal Table中缓冲,需要的时候直接从缓冲中读取,避免重复访问数据库,这样也可以有效减少INNER JOIN的数量。

下面一种缓冲模式的实现,通过使用静态变量,使访问缓冲数据的实现全部封装在一个函数内:
  1. FORM get_person_name USING id  
  2.                   CHANGING name.  
  3. * 定义缓存表类型  
  4.   TYPES: BEGIN OF ts_person,  
  5.             id(10) TYPE c,  
  6.             name(10) TYPE c,  
  7.          END OF ts_person.  
  8. * 定义缓冲表  
  9.   STATICS: it_person TYPE HASHED TABLE OF ts_person WITH UNIQUE KEY id.  
  10.   FIELD-SYMBOLS: <fs> LIKE LINE OF it_person.  
  11. * 如果是第一次调用,初始化缓冲表  
  12.   IF it_person[] IS INITIAL.  
  13.     " TODO: 从数据库中读取所有记录  
  14.   ENDIF.  
  15. * 从缓冲表中读取记录  
  16.   READ TABLE it_person ASSIGNING <fs> WITH TABLE KEY id = id.  
  17.   IF sy-subrc = 0 .  
  18.     name = <fs>-name.  
  19.   ELSE.  
  20.     name = ''.  
  21.   ENDIF.  
  22. ENDFORM.                    " get_person_name  
复制代码

3. 减少循环嵌套的层数
循环嵌套会造成循环次数倍数级的增长,造成程序执行缓慢,所以要尽量避免循环嵌套的产生,特别避免产生三层以上的嵌套循环。但是有时候我们难免需要嵌套循环,这个时候必须预估每个循环最大可能发生的次数。如果把那些循环次数相对固定的称为固定次数循环,那些随数据量的增加,循环次数明显增加的称为可变次数循环,那么一个嵌套循环应该只出现一个可变次数循环。这样才能保证循环次数的可控。如果不能做到,我们应该要考虑重写代码的逻辑。

同时,我们应该尽量避免在循环中使用SELECT或者读取Standard Table,因为这两种方式读取数据的效率比较低,多次调用,累加的时间是巨大的。
如果有可能,我们应该尽量减少循环嵌套。这样能明显提高程序的性能。如以下代码:
  1. FIELD-SYMBOLS: <fs_kkna1> LIKE LINE OF git_kkna1,  
  2.                  <fs_vvbak> LIKE LINE OF git_vvbak.  
  3.   LOOP AT git_kkna1 ASSIGNING <fs_kkna1>.  
  4.     LOOP AT git_vvbak ASSIGNING <fs_vvbak> WHERE kunnr = <fs_kkna1>-kunnr.  
  5.       " todo: process data  
  6.     ENDLOOP.  
  7.   ENDLOOP.  
复制代码

通过修改,我们可以去掉一个嵌套,虽然代码多了点:
  1. FIELD-SYMBOLS: <fs_kkna1> LIKE LINE OF git_kkna1,  
  2.                <fs_vvbak> LIKE LINE OF git_vvbak.  
  3. SORT git_kkna1 BY kunnr.  
  4. SORT git_vvbak BY kunnr.  
  5. LOOP AT git_vvbak ASSIGNING <fs_vvbak>.  
  6.   AT NEW kunnr.  
  7.     READ TABLE git_kkna1 ASSIGNING <fs_kkna1>  
  8.                           WITH KEY kunnr = <fs_vvbak>-kunnr  
  9.                           BINARY SEARCH.  
  10.     IF sy-subrc NE 0.  
  11.       UNASSIGN <fs_kkna1>.  
  12.     ENDIF.  
  13.   ENDAT.  
  14.   IF <fs_kkna1> IS NOT ASSIGNED.  
  15.     CONTINUE.  
  16.   ENDIF.  
  17.   " TODO: process data  
  18. ENDLOOP.  
复制代码

AT NEW语句用法:整理内表数据control level的使用方法

4. 合理使用READ TABLE

READ TABLE有三种方式,一种是读取Standard Table,通过WITH KEY方式;一种是读取Sorted Table,通过WITH KEY…BINARY SEARCH读取,但是必须先对关键字排序;最后一种是读取一个Hash Table,通过WITH TABLE KEY方式读取数据。

通过性能测试,我们发现:
  • Hashed Table和Sorted Table读取的效率最高,基本接近,Hashed Table比Sorted Table效率稍高点;
  • Standard Table和Select读取效率很差,在数据量增大的情况下,Standard Table的读取效率居然不如直接从数据库中访问。

所以我们应该使用Hashed Table或Sorted Table来访问数据,特别是循环嵌套中,更必须如此。注意,通过BINARY SEARCH读取的时候,一定要先对读取的表按关键字排序。

4.增加表索引
增加条件字段的索引能够明显增加查询数据的速度。

6. 后台任务
数据量的增加肯定会使程序运行时间增加。通常那些运行时间不合理增长的程序能够通过优化改善性能,但是运行时间合理增长的程序,就很难优化,对于这类程序,我们只能优化用户的感觉了,让用户不至于因程序的长时间运行而感到烦躁。譬如通过后台任务运行程序,然后把运行结果呈现给用户。

7. 增加进度条
对于一些很难优化,但运行时间相对较长的程序,如运行时间长达1分钟。我们可以给程序加上进度条,改善用户体验。

8. 优化程序结构
一种方式是在不变更业务逻辑的前提下,对程序的代码逻辑进行重构,修改不合理的代码结构,提升运行的性能。

另一种方式是在满足业务需求的前提下,重新调整影响性能的业务逻辑。

总结
总之,通过认真的分析和合理的方法,大多数ABAP程序是可以进行性能优化的。
回复

使用道具 举报

qshiou
leon大神,我现在一般都只是用STANDARD TABLE ,读取时排序用BINARY SEARCH,现在的需求中并没有发现问题,不过我看帖子都说用排序表和哈希表好,您能讲讲什么时候用吗?
回复 支持 反对

使用道具 举报

Twilight
qshiou 发表于 2015-7-21 18:00
leon大神,我现在一般都只是用STANDARD TABLE ,读取时排序用BINARY SEARCH,现在的需求中并没有发现问题,不 ...

以后再讲吧,最近在将增强,你没事可以从网上找些资料,自己写个demo研究一下
回复 支持 反对

使用道具 举报

qshiou
恩恩 非常感想分享,看您的帖子对我帮助很大
回复 支持 反对

使用道具 举报

快速回帖

本版积分规则
您需要登录后才可以回帖 登录 | 注册有礼

快速回复 返回顶部 返回列表