【优化】关于索引的总结

最近在优化一个别人做的报表,该报表是一个记录从销售到交货装运的全过程报表,需要读取销售订单、转储单、交货单、装运单上的相关信息,报表开发完毕传输到测试系统中会出现timeout。

后来通过se30 abap运行时间分析,找到了问题的源头,在程序中有一处需要读取交货凭证和收货凭证代码如下:

     LOOP AT lt_tkdc.”装运单内表(业务限制一张装运单上面只有一张交货单)
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = lt_tkdc-vbeln_dc ”装运单上的交货单号
        IMPORTING
          output = lt_tkdc-vbeln_dc.
      SELECT SINGLE mblnr INTO lt_tkdc-mblnr_dc FROM mkpf WHERE xblnr = lt_tkdc-vbeln_dc AND blart = 'WL'.  "发货
      SELECT SINGLE mblnr INTO lt_tkdc-mblnr FROM mkpf WHERE xblnr = lt_tkdc-vbeln_dc AND blart = 'WE'.  "收货
      MODIFY lt_tkdc TRANSPORTING  mblnr_dc mblnr.
          CLEAR lt_tkdc.
    ENDLOOP.

这段代码中通过select single去读取mkpf,查询条件为xblnr和blart,这两个字段并非mkpf的主键和索引(mkpf的主键是物料凭证号和会计年度;mkpf系统自带了一个索引BUD,该索引是按凭证中的过帐日期)。在测试环境中mkpf的记录大概有460万条,加上外部lt_tkdc这个内表,假设用户通过筛选条件取到大概20条数据,那么读取mkpf表的次数将达到20*2*460万 = 18400 万次,所以通过这种select single方式读取肯定是会出现timeout的。

考虑的方案,将读取mkpf表拿到LOOP外面一次行读取,然后再loop里面通过二分查找read出发货和收获凭证。但一次性读出来可以使用for all entries in交货单的内表,但是还是利用不了索引。所以考虑了两种办法:1、为MKPF建立XBLNR的索引。2、通过交货单取到交货单的货物实际移动日期,作为物料凭证过账日期,这样使用系统的索引BUD索引。

使用create extension index 和create index创建好的索引在sap页面显示上面有什么区别呢?

答案:扩展索引自动复制在升级过程中不会被带过去也就是说系统升级可能会导致这个extension的索引丢失。如果你希望你建立的索引在下一个sap交付的标准版本中依然存在,你应该使用create index。在所有其他情况下,你应该创建一个扩展索引(create  Extension index)。


关于索引的sap官方文档:

http://help.sap.com/erp2005_ehp_04/helpdata/EN/cf/21eb20446011d189700000e8322d00/frameset.htm

在sap help文档上有这么一段:Whatto Keep in Mind for Secondary Indexes 

1、 二级索引,在表内容发生变化时他们都必须调整,因此每个额外的索引都会减慢插入表中的记录。所以对于频繁修改的表不适合建立太多的索引。

2、 假如我们定义了表bsptab的一个FIELD1、FIELD2、FIELD3 和FIELD4的索引,这张表有如下一段查询语句:

Select * from bsptab where field1 = x1 and field2 = x2 andfield4 = x4.

那么这个索引是怎么使用的呢?

   从上面的语句我们可以看出,field3未指定。其实我们才平常的开发中经常会碰到此类问题,比如系统中已经有了某个索引,而我们又不能使用到该索引的全部字段。其实上面这段语句只会选择到所有field1 = X1 和 field2 = X2的条目到索引,而field4的全部记录都在索引中,并为被限制成x4。

   所以说索引中字段的顺序是也很大程度上会决定访问速度。对于大数据的选择,第一个字段应该选择一些恒定值

3、 表的索引,应该尽可能的松耦合。如果两个索引在表上有大量的共同字段,这样会使优化性选择最有选择性的条目变得更加困难。

4、 如果是建立uniqueindexes必须要保证index的字段筛选表条目的唯一性。

ABAP TABLE BUFFER

Index可以被看成是表记录的特殊几个字段的copy。这个copy是排序的,这样可以提高查询表的性能。Index中含有指针用于指向其在表中所在的位置。

使用index时的注意事项:

l         要利用Index提升性能,索引字段必须位于where子句的最前面。

l         只用那些可以明显的减少记录数量的字段才适合作为索引。

l         当修改表中的记录时,索引的顺序就会被改变,所以对于频繁修改的表不适合建索引。

l         一个表中不同的索引的耦合要尽量松散

当要去表中的记录时database optimizer会决定应当使用那个index。用户可以创建自己的index但是必须以Y或Z开始。在创建索引是你可以选择在那些类型的数据库中创建索引。

Table buffer可以大大提高访问表的性能。随着数据的增加对缓存的空间要求越来越多较长时间没有被访问到得数据就会被置换掉。只有当缓存剩余的空间小于阀值或访问性能没有达到要求时缓存中的数据才会被置换掉。可以再command field中敲入/$TAB来清空所在application server上的缓存。/$SYNC可以清空所在application server上的所有缓存。

SAP系统在每个application server上管理和同步缓存。当程序读取表的数据时database interface首先到application server得缓存中去查看是否有符合条件的数据如果有就直接从换从中读取,如果没有就到数据库中去读取,然后把读取到的数据放到缓存中。

按照往换从放数据方式的不同可以分成三种缓冲类型:

l         Full buffer:当表中的一条记录被访问时,所有的记录都会被放到缓存中

l         Genric buffer:访问到得记录的key的左连接(left join)被缓存。

l         Single-record buffer:只有被访问到得记录被缓存。

Fully buffer:比较小的表,很少被修改适合fullybuffer。对于那种场景是表中的记录不存在的查询经常被使用的表也适合做fully buffer。另外对于fully buffer由于buffer中的记录是按照key排序的所以查询条件要充分利用索引,否则的话很有可能性能还没有直接从数据库中访问利用secondaryindex好。

Single-record buffer适合于select single语句对于select single找不到记录的情况,buffer中也会记录这种情况下找不到,下次使用这个语句时就不会再读取数据库了。

由于buffer是在服务器本地管理的,buffer中的数据必须与数据库同步。同步的动作在一定周期内发生,这个周期是有参数rdisp/bufreftime设置的。

Buffer在application server本地保存的有点时减少了网络流量,缺点是在buffer中可能存在脏数据。所以使用buffer时应当注意这几点。

Note 821722

 

 

 

注:SM66 可以知道查询过程中是否用上了索引


你可能感兴趣的:(SAP,PERFORMANCE,TUNING)