ABAP程序优化的一些总结
第一部分 程序运行时间的优化
优化的重点之一是运行时间,影响运行时间的因素有很多,首先程序本身的话,从CPU角度讲,指令越少自然运行时间越快,会引发CPU大量操作的基本上主要就是对数据量非常大的内表进行循环处理(LOOP)的时候,下面列举一些比较有效的可以优化的地方:
嵌套循环(NESTEDLOOP),如果外循环有N条记录,内循环有M条记录,那么总的循环次数就是N*M,这是需要避免或者优化的,一个比较常用的方法是在LOOP后面加上WHERE条件,这样可以避免了全表循环,在一些特殊场合(比如排序过的内表),可以使用一些编程技巧用INDEX FROM TO直接指定需要LOOP的内表所在行。
二分法查找(BINARYSEARCH):假如LOOP里有需要用到READ TABLE去查询另外一个内表里的某条记录,那么先对那个内表进行需要比较的KEY值的排序,再用BINARY SEARCH能显著提高查询速度。如果不指定BINARY SEARCH关键字,系统会按顺序作全表扫描和比较,扫描一个有N条记录的内表,在最坏情况下需要比较N次(假如所需要的记录正好在内表的最后一条),而用BINARYSEARCH查找是折半查找,则只需要比较LOGN次。比如当N是100万时,普通查找最多可能查找100万次,而折半查找最多只需要查找20次。
FIELD-SYMBOL:LOOP时使用FS来代替结构(工作区),这样的好处是直接定位到内表的某条记录,而不是复制这条记录到结构里(所以在修改内表内容时,使用指针不需要MODIFY命令,因为指针是直接修改内表的内容,而结构只是内表当前行的一个拷贝,修改完结构之后需要通过MODIFY复制回内表)。同样的READTABLE也一样可以ASSIGNING到一个指针里,但是和LOOP不同的是,LOOP ASSIGNING是必定成功的,而READ TABLE ASSINGING可能失败,当失败时,这个指针是不能使用的,不然运行时会发生指针未分配的DUMP。建议可以定义一个同类型的结构(初始值),如果READ TABLEASSIGNING失败,就把指针分配到这个结构里。
*使用指针来进行LOOP基本上总是有利的且没有什么副作用,但是个人认为从原理上看,有的时候可能优化的重点并不是LOOP时用指针去代替结构,假如LOOP里的数据处理才是重点的话,那么省去复制到结构的这步操作也不会对运行时间产生很大的影响。
数据库操作:这点其实属于数据库开销的方面的优化。LOOP里基本不允许SELECT,一次完整的SELECT所需要的时间相对是较多的(可能只有零点零几秒,但是一旦循环几十万上百万次的话……),一般是先用FOR ALL ENTIRES把全部数据读入另外一个内表,然后和LOOP里面READ TABLE(BINARY SEARCH)来代替。同理在作INSERT和UPDATE的时候,也尽量通过内表批量处理,避免在LOOP里根据结构作单条插入或更新。
*这样做虽然提升了时间上的效率,但内存和数据库传输数据开销是增加了,因为需要从数据库读入更多的数据到内表,可能导致内存不够的问题,具体会在后面的内存空间相关的部分讲。
调用功能模块(Function Module)和方法(Method):有的时候会在LOOP里调用标准的FM,标准的FM通常比较复杂,内部有多层次的调用,里面可能会有SELECT语句,这种情况下可以自己写逻辑从数据库取数来代替调用标准FM。
并行处理(Parallel Processing):并行处理是指开多个进程同时处理,SAP有多种进程,前台进程(DialogProcess)和后台进程(BackgroundProcess)是其中的两种,并行可以分为前台并行(占用前台进程)和后台并行(后台进程),前者采用异步RFC,关键字CALLFUNCTION STARTING NEW TASK,后者采用JOB OPEN和SUBMIT VIA JOB的方法。并行处理是在处理大量数据时非常有用的方式,除了可以显著地提升时间效率之外,也可以解决单个进程有最大内存的限制。但是并行也有局限性,比如说同时处理的数据不能有逻辑上的关联性,而且每个进程的执行先后顺序也是不可预料的。
第二部分 内存空间的优化
SAP Unicode程序,一个C类型的字符占用两个字节(2Byte)。内存设置方面,分配给一个前台进程(Dialog Process)默认是4000000000字节(2000000000的Extended Memory和2000000000的Heap Memory,这个大小可以调整),也就是不到4GB的内存空间,当一个内表的行结构是512个字符(1024个字节时),最多大约可以容纳400万条不到的记录数,如果超过了这个容量,就会发生DUMP或者程序强制关闭。
解决方法是SELECT取数时改为使用SELECT PACKAGE SIZE ENDSELECT分包取出并处理,这样可以在规定的内存大小内完成数据的处理。但是这种方法依然有个小问题,就是在SELECT和ENDSELECT里不支持并行进程(从原理上讲并行会涉及到进程切换,进程切换时会触发一个COMMITWORK,而在SELECTENDSELECT里这是不允许的),如果要达到分包取数并且并行处理的效果,就需要使用OPEN CURSOR和FETCH。
关于赛锐信息
作为SAP的资深合作伙伴,赛锐信息是一家专业提供SAP行业化管理软件解决方案的顾问公司,致力于为企业提供SAP ERP系统咨询服务、IT规划、业务流程优化、信息系统实施、行业信息系统方案开发,运营外包及售后维护等全面的服务方案。已服务1000+家不同行业、规模的大中小型企业客户。在电子高科技、汽车零部件、印刷包装、医疗器械、快消品、专业服务等行业信息化管理领域具有领导性地位。