用织梦做的网站怎么管理系统,wordpress关闭手机访问,wordpress插件自动,临沂房产和房建设局网站双和1.前言
ABAP作为SAP的专用的开发语言#xff0c;衡量其性能的指标主要有以下两个方面#xff1a;
响应时间#xff1a;对于某项特定的业务请求#xff0c;系统在收到请求后需要多久返回结果 吞吐量#xff1a;在给定的时间能#xff0c;系统能够处理的数据量 2. ABAP语…1.前言
ABAP作为SAP的专用的开发语言衡量其性能的指标主要有以下两个方面
响应时间对于某项特定的业务请求系统在收到请求后需要多久返回结果 吞吐量在给定的时间能系统能够处理的数据量 2. ABAP语言的运行原理 首先先了解下SAP系统基本架构看一看ABAP程序的运行原理。
SAP自从R/3开始使用三层架构的系统模型即
表现层可通过SAPGUI或浏览器等方式执行具体的SAP应用程序 业务逻辑层ABAP应用程序运行在SAP NetWeaver的ABAP应用服务器上 数据库访问层在程序运行过程中对DB2或HANA等数据库的访问 在下图的展示中可以看到SAP系统也是由最底层文件系统数据库管理系统应用服务器、表现层的UI构成。 ABAP语言的执行环境是ABAP应用服务器其为ABAP程序分配运行所需要内存、工作进程。由此可以看到ABAP程序的主要用时有两个方面
一是由程序复杂度决定的work process的运行时间
另一部分是在运行过程中对不同位置的数据访问增、删、改、查时间。 3. 在哪些方面进行优化 当访问不同位置的数据时所需要消耗的时间单位也是不同的。由于硬盘转速的物理极限和数据库的通信连接等原因访问数据库硬盘的时间消耗要较访问应用服务器内存中的数据时间花费的要更多。访问各部分的时间消耗关系是访问数据库 访问数据库缓存 共享内存/缓存 工作进程。
因此对于ABAP程序的性能优化可从以下角度介绍使用场景和运用过程中的最佳实践。包括
如何合理地访问数据库 如何使用数据库缓存 如何选用内表 如何使用batch job … ABAP性能调优工具的使用等
【01】SAP ABAP性能优化 - 如何减少DB的访问次数
方法1尽量使用内表进行数据库的批量操作.
这个原则很好理解例如要向数据库中插入100条数据那么可以通过内表批量操作。
与其使用一般的 loop-endloop 方法来实现向内表添加多条记录不如使用 append 命令的变体将一个内表的所有记录一次性添加入另一个内表。要注意的是两个内表的结构定义必须完全一样。
* -- Bad -- *
LOOP AT lt_sflight INTO ls_sflight.INSERT INTO sflight VALUES ls_sflight.
ENDLOOP.* -- 推荐使用1-- *
INSERT INTO sflight FROM TABLE lt_sflight.* -- 推荐使用2-- *
Append lines of int_fligh1 to int_fligh2.修改一个内表的多行纪录 使用modify命令的不同形式加快这种操作的处理速度
不建议使用Loop at int_fligh.If int_fligh-flag is initial.Int_fligh-flag ‘X’.Endif.Modify int_fligh.Endloop.建议使用Int_fligh-flag ‘X’.Modify int_fligh transporting flag where flag is initial. 方法2使用Join进行在DB层级进行数据的处理 如果通过JOIN能够完成数据的处理则尽可能减少在ABAP的AS进行处理。
* -- Bad -- *
SELECT carrid connid fldate FROM sflight INTO (xcarrid, xconnid, xfldate) WHERE planetype 727-200.SELECT bookid FROM sbook INTO ybookidWHERE carrid xcarridAND connid xconnidAND fldate xfldate.WRITE: / xcarrid, xconnid, ybookid.ENDSELECT.
ENDSELECT.* -- Good-- *
SELECT f~carrid f~connid b~bookidINTO (xcarrid, xconnid, ybookid) FROM sflight AS fINNER JOIN sbook AS bON f~carrid b~carrid AND f~connid b~connid AND f~fldate b~fldateWHERE planetype 727-200.WRITE: / xcarrid, xconnid, ybookid.
ENDSELECT.方法3使用视图取代基本表将常用的INNER JOIN创建成DDIC的JOIN VIEW
通过这种方式在ABAP程序中可以直接使用VIEW来读取数据多个表的JOIN数据集。 方法4使用子查询 当需要对同一张表进行多次访问时可以考虑使用子查询的方式减少DB的访问次数。
* 举例确定哪一天的航班预定出座位最多的* 方式1双层select。首先选择出预定最多的航班信息再确定具体的日期。
DATA: ls_sflight TYPE sflight,lv_max TYPE i.
SELECT carrid connid MAX( seatsocc )FROM sflightINTO (ls_sflight-carrid, ls_sflight-connid, lv_max)GROUP BY carrid connid.SELECT fldate FROM sflightINTO ls_sflight-fldateWHERE carrid ls_sflight-carridAND connid ls_sflight-connidAND seatsocc lv_max.WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.ENDSELECT.ENDSELECT.* 方式2使用子查询。单层SELECT直接选择出航班信息和日期信息将最大的座位数在子查询中确定。
SELECT carrid connid fldateFROM sflight AS fINTO (ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate)WHERE seatsocc IN ( SELECT MAX( seatsocc )FROM sflightWHERE carrid f~carridAND connid f~connid ).WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDSELECT.【02】SAP ABAP性能优化 - 如何减少与DB交互的数据量
为提升程序性能在ABAP编程过程中应尽量减少DB的访问次数。与此同时在访问DB时还应尽量减小在与DB交互的数据量这样可减小DB通信的网络负担提升访问速度。可通过下面方式达到“减少DB交互数据量”的目标。
方式1 避免 SELECT *
这一点很好理解也就是在搜索时显性指定所需的字段。尽量避免返回不必要的数据因为任何一个字段的选取DB都会进行相关的遍历查找与DB交互时应尽量将数据遍历时间降到最低。
不要图方便使用SELECT * FROM sflight INTO CORRESPONDING FIELD 这样的语句。
方式2使用WHERE语句限定搜索范围
这一点不做过多解释合理地使用WHERE语句是任何一种编程语言的通用规范。
方式3避免在SELECT … ENDSELECT中使用CHECK等类似的判断语句
原因同第二点合理地通过WHERE限定数据集仅选取有效的数据进行处理而非在选取后再判断数据的有效性。
方式4使用UP TO n ROWS来限定结果集数目
使用UP TO n ROWS特别适用于选取特定条件、特定数目的SELECT。看下面的例子从DB中选取10位折扣最大的客户应直接使用UP TO 10 ROWS, 而非每一次手动计数。
DATA: ls_scustom TYPE scustom,lt_scustom TYPE TABLE OF scustom WITH EMPTY KEY.* -- Bad --*
SELECT id name discountFROM scustomINTO (ls_scustom-id, ls_scustom-name, ls_scustom-discount)WHERE custtype BORDER BY discount DESCENDING.IF sy-dbcnt 10.EXIT.ENDIF.WRITE:/ ls_scustom-id, ls_scustom-name, ls_scustom-discount.
ENDSELECT.* -- Good --*
SELECT id name discountFROM scustom UP TO 10 ROWSINTO CORRESPONDING FIELDS OF TABLE lt_scustomWHERE custtype BORDER BY discount DESCENDING.方式5在SELECT中使用聚合函数完成运算. 使用提供的集合函数取代代码来获得最大或最小值等。 其它可用集合函数还有 min (最小值), avg (平均值), sum (求和) and count (数据选择的行数). 在SELECT中使用例如COUNTSUMMAX等函数完成数据的统计工作直接返回运算结果。
DATA: lv_seatsocc TYPE sflight-seatsocc,lv_sum TYPE i VALUE 0.* -- Bad --*
SELECT seatsoccFROM sflight INTO lv_seatsoccWHERE carrid LHAND fldate LIKE 2018%.lv_sum lv_sum lv_seatsocc.
ENDSELECT.* -- Good --*
SELECT SUM( seatsocc )FROM sflightINTO lv_sumWHERE carrid LHAND fldate LIKE 2018%.方式6使用UPDATE …SET更新数据库 如果只需要更新DB中某一条数据中的特定几个字段使用UPDATE … SET无疑是最佳的方式。
DATA: ls_sflight TYPE sflight.
SELECT * FROM sflightINTO ls_sflight UP TO 1 ROWSWHERE carrid LH.
ENDSELECT.
* option 1 -
ls_sflight-price ls_sflight-price 100.
UPDATE sflight FROM ls_sflight.
* option 2 -
ls_sflight-price ls_sflight-price 100.
UPDATE sflight SET price ls_sflight-price
WHERE carrid ls_sflight-carridAND connid ls_sflight-connidAND fldate ls_sflight-fldate.【03】ABAP性能优化-语法上
ABAP程序基本上都需要从数据库里面抓数所以性能很重要同时有一些基本的和优秀的写法是我们必须要掌握的不然就会造成程序性能很差。下面给予总结这里包括有很基本的也包括有比较少用到的推荐一个好的SAP标准文档ABAP_PERFORMANCE_DOS_AND_DONTS
一、基本的几条需要避免的规则具体的一些怎么替换可以看三和五 1、不使用select....endselect。 2、基本不使用select * select 需要的字段数据量大时容易内存溢出dump。 3、LOOP 里面不用sort 在loop外面排序完再进入LOOP。 4、尽量避免LOOP 里面嵌套select这样多次访问数据库也会造成性能问题但是有些时候避免不了也难免。改为外面selectLOOP里面read table。 5、大数据的read table使用二分法查找 BINARY SEARCH用之前要按关键字排序。
READ命令使用顺序查找数据表这会降低处理速度。取而代之使用binary search的附加命令可以使用二分查找算法可以帮助加快内表查找速度。 在使用binary search之前必须首先将内表排序否则有可能找不到记录因为二分查找反复将查找区间对半划分如果要查找的值小于查找区间的中间位置的数据项值则查找区间将缩小到前半个区间否则查找将局限于后半区间。 不推荐使用Read table int_fligh with key airln ‘LF’.推荐使用SORT int_fligh by airln.
Read table int_fligh with key airln ‘LF’ binary search. 6、尽量避免LOOP里面嵌套LOOP特别是当两个内表数据量都很大的时候如果实在要嵌套LOOP可以参考三和五里面的解决办法。 7、尽量避免LOOP里面不用deleteappend等语句。改成批量处理。
二、index和buffer的合理使用
1、index的使用在使用现有的index的时候注意where条件里面的字段的顺序要跟index一致而且可以可以适当的去匹配index创建一些空的字段或者是index后面再加字段或者是使用index抓出数据后再去做其它条件的处理。
2、index里面最好只有 AND 或者是‘IN’。有其它逻辑条件会影响index的使用。
3、 如果表是有buffer可以考虑使用buffer这样性能也可以有很好的提升不过首先要去表看看这个是否有buffer
SELECT SINGLE * FROM T100 INTO T100_WA
BYPASSING BUFFER
WHERE SPRSL D.
4、使用缓存表。大部分表都有buffer而且这个我们很难控制但是我们写出来的语句要尽可能避免“不读buffer”在 select 命令后面使用 bypass buffer 附加语句可以明确跳过缓存表。推荐使用缓存表因为它可以显著提高程序速度。但是使用以下语句的时候缓存表会被跳过
Select distinctSelect … for updateOrder by, group by, having字段Joins
5、一般程序到表抓数的时候会在应用服务层有数据缓存所以同一个程序在不同时间先后跑后面的通常会比较快因为可以到数据缓存读数。
6、NOT只能全表扫描不要用not换成反面。建议between 换成IN。不建议使用LIKE OR
三、使用一些简单的语句代替复杂的嵌套LOOP
1、用批量处理的BAPI替换LOOP 里面call BAPI例如用BAPI_MATERIAL_SAVEREPLICA 替代 BAPI_MATERIAL_SAVEDATA
2、LOOP 里面delete可以改成给内表加一个flag的字段然后需要删除的打上X然后用Delete it_1 where delete ‘X’.
3、LOOP AT 搭INSERT或者是APPEND可以改成 INSERT SBOOK FROM TABLE itab。 APPEND LINES
4、如果是两个内表都很多数据但是逻辑要进行嵌套LOOP可以如下处理会提升一些性能 1.1.1 多层/嵌套LOOP循环性能优化写法
SORT:lt_ztfi0005 BY hcode,lt_prj_prps BY pbukr,lt_prhi BY up,lt_phs_prps BY pspnr.LOOP AT lt_ztfi0005 INTO ls_ztfi0005.
“ 第一层双层LOOP循环优化READ TABLE lt_prj_prps TRANSPORTING NO FIELDSWITH KEY pbukr ls_ztfi0005-hcode BINARY SEARCH.IF sy-subrc 0.lv_cmp_ix sy-tabix.LOOP AT lt_prj_prps INTO ls_prj_prps FROM lv_cmp_ix.IF ls_prj_prps-pbukr ls_ztfi0005-hcode.EXIT.ENDIF.
“ 第二层双层LOOP循环优化READ TABLE lt_prhi TRANSPORTING NO FIELDSWITH KEY up ls_prj_prps-pspnr BINARY SEARCH.IF sy-subrc 0.lv_prhi_ix sy-tabix.LOOP AT lt_prhi INTO ls_prhi FROM lv_prhi_ix.IF ls_prhi-up ls_prj_prps-pspnr.EXIT.ENDIF.READ TABLE lt_phs_prps INTO ls_phs_prpsWITH KEY pspnr ls_prhi-posnr BINARY SEARCH.IF sy-subrc 0.CONTINUE.ENDIF.ls_data-cmp_nr ls_ztfi0005-hcode.ls_data-cmp_nm ls_ztfi0005-hname.ls_data-prj_nr ls_prj_prps-posid.ls_data-phs_nm ls_phs_prps-post1.APPEND ls_data TO et_data.CLEAR ls_data.ENDLOOP.ENDIF.ENDLOOP.ENDIF.ENDLOOP.5、LOOP 后面用assigning 指针的方式这样也可以节省空间和时间可以省去了appendmodify等操作在嵌套LOOP没法像上面那样解决的话也建议使用指针。
四、有一些标准的FM如果在LOOP里面使用可以考虑换成使用自己开发把抓数放出来然后readread_text
1、有很多程序要调用FM read_text但是当用到LOOP里面调用这个read_text会比较慢其中到STXH表抓数就会占用很多时间我们可以考虑对read_text进行优化把read_text分成两个FM一个是集中读取STXH然后另一个是和read_text一样的功能只是把抓数换成read table。占用性能就会提高很多。
五、一些优秀的良好的ABAP 程序书写习惯
1、select 数据的时候如果可以使用join进行内联尽量2-3个表内联即可。下面这个图可以理解下join的用法
有时join太多了也可以考虑使用创建视图然后从视图里抓数例如vbak_kan1。
2、如果要select 数据出来更改一些字段的值再进行updata可以考虑直接使用updata set省去到表里面抓数
SELECT * FROM sbookINTO xbookWHERE carrid LHAND connid 0400 AND fldate 20110101.xbook-connid 0500.UPDATE sbook FROM xbook.ENDSELECT.UPDATE sbookSET connid 0500 WHERE carrid LH AND connid 0400 AND fldate 20110101. 3、读取HASHED表会比其他两种类型更快同时read table 也可以通过transporting 某些字段到work area不用全部字段都用上。
4、有些表的数据是很固定的例如KNA1或者是T001等可以抓大部分数据放到内表里然后去读取如果读取不到在抓不用每次都抓。
5、强制使用索引但是如果更改数据库了就会失效了 %_HINTS DB6 这个不太建议使用但是当ST05分析之后是可以使用某个索引但系统没有使用就可以使用这个语句强制使用索引。
6、及时清空不再使用的大内表释放内存。当一个report在ALV显示完之后在end-of-selection里面把不用的内表的清空掉防止有些后台job一次跑两个变量的时候会重复同时释放内表也是减少内存压力。
7、field-groups的使用对于多层次的排序和显示非常有用。
8. 使用 “for all entries” 注意使用前判断内表不为空否则导致全查询严重影响性能。 在select语句后面的where附加项中可以使用左关联这会极大的提高程序速度但同时也有一些局限如下 重复项会被从结果数据集中自动删除因此要注意在select语句中需要给出详细的唯一关键字组合。 如果 For All Entries IN 字段修饰的内表是空表的话源表的所有行都会被选入目标表中。因此在使用前一定要首先检查第一个表是否为空这一点很重要否则会有performance问题。 如果 For All Entries IN 字段修饰的内表很大的话程序速度反而会减慢而不是加快。因此应该尽量使该表的数据量控制在一个适当的大小。