ABAP程序优化

程序优化这个易学,但是难以达到一个完美的地步,我在日常联系中也不确定某段代码选择的优化写法是不是最好的,所以以下代表的我一些个人看法。

在具体介绍优化方法之前,先介绍两个工具,SAT(原SE30)和ST05,SAT用来分析程序效能问题,ST05来确定SQL是否用到了INDEX,SAT除了可以直接测前端,也可以在schedule中后台测试,但是后台的不能时间太大,否则超过一定范围会无效,

优化方法:

1、选择合适内表,例如在用DN+Item寻找Billing + Item、SO + Item寻找DN + Item的时候优先使用VBFA而不是LIPS/VBRP,在寻找工单发料的记录的时候优先使用AUFM而不是MSEG(注:即使mseg中有一些aufm没有的索引,但由于数据量远超过aufm,效能上依旧比不上)

2、SQL部分的优化:

1)、ST05中如果发现没有触发index,最好让建一个,但是不是什么table都能建,对那种数据量已经很大的table千万不要

2)、FOR ALL ENTRIES IN一定需要小心使用,虽然用起来挺方便的,效能上经常出问题:需要check以下是否为空,这个一般都不会在这个上面犯错;对for all entries in的对象行项目最好不要超过5000,因为如果用ST05去分析运行时的SQL,会发现其实这是用很多的OR去作为where条件去遍历这个数据库,所以一般出了效能问题就需要做一些调整,一般有两个方向,方向一:如果只用到entries in对象中的一个条件,可以改用range table的形式,但需要注意,range table不可以超过20000行,不然会发生dump;方向二:在DO循环中5000一批次做for all entries in ,

注:in range 其实是open sql的语法,在ST05中其实会翻译成native sql,这样range table里面的内容其实会翻译成多个 or 结合的语句,当超过20000行的时候,整个SQL语句占据的内存会超过限定。

  IF gt_ywsdn_in_transit1[] IS NOT INITIAL.
    CLEAR: lv_line,lv_time.
    lv_line = lines( gt_ywsdn_in_transit1 ).
    lv_time = ceil( lv_line / 4000 ).
    DO lv_time TIMES.
      REFRESH:gt_ywsdn_in_transit1_tmp.
      lv_from = ( sy-index - 1 ) * 4000 + 1.
      IF sy-index = lv_time.
        lv_to = lv_line.
      ELSE.
        lv_to = sy-index * 4000.
      ENDIF.
      APPEND LINES OF gt_ywsdn_in_transit1 FROM lv_from TO lv_to TO gt_ywsdn_in_transit1_tmp.

      SELECT    lips~vbeln
                lips~posnr
                lips~matnr
                lips~werks
                lips~lfimg
                lips~meins
                lips~vgbel
                lips~vgpos
            likp~wadat_ist
            likp~vkorg
       APPENDING CORRESPONDING FIELDS OF TABLE lt_lips
       FROM lips
       INNER JOIN likp ON lips~vbeln = likp~vbeln
       FOR ALL ENTRIES IN gt_ywsdn_in_transit1_tmp
       WHERE lips~vbeln = gt_ywsdn_in_transit1_tmp-vbeln
       AND   lips~posnr = gt_ywsdn_in_transit1_tmp-posnr.
    ENDDO.
  ENDIF.
  IF lr_likp[] IS NOT INITIAL.

    SORT lr_likp BY low.
    DELETE ADJACENT DUPLICATES FROM lr_likp COMPARING ALL FIELDS.

    ls_likp = 'IEQ'.
    MODIFY lr_likp FROM ls_likp TRANSPORTING sign option WHERE sign = space.

    CLEAR:lr_likp_tmp,lv_line,lv_time.
    lv_line = lines( lr_likp ).
    lv_time = ceil( lv_line / 20000 ).

    DO lv_time TIMES.
      REFRESH:lr_likp_tmp.
      lv_from = ( sy-index - 1 ) * 20000 + 1.
      IF sy-index = lv_time.
        lv_to = lv_line.
      ELSE.
        lv_to = sy-index * 20000.
      ENDIF.
      APPEND LINES OF lr_likp FROM lv_from TO lv_to TO lr_likp_tmp.

      SELECT vbeln
             posnr
             parvw
             kunnr
             adrnr
       APPENDING TABLE lt_vbpa
       FROM vbpa
     WHERE vbeln IN lr_likp_tmp
           AND posnr = '000000'
           AND parvw = 'WE'.

      SELECT shorg
             dono
             cfm_date
        APPENDING TABLE lt_yexpiv06
        FROM yexpiv06
       WHERE shorg IN shorg
         AND dono IN lr_likp_tmp.

    ENDDO.

3)、SQL中不要使用INTO CORRESPONDING FIELDS OF TABLE,尽量使用 INTO TABLE

4)、SQL使用EXISTS子查询对主查询进行过滤,

  SELECT aufnr werks objnr INTO TABLE lt_aufk
    FROM aufk
    WHERE werks IN s_werks       "modify by nelson 20161112
    AND aufnr IN s_aufnr
    AND loekz NE 'X'
    AND EXISTS ( SELECT * FROM jest WHERE objnr = aufk~objnr AND  inact NE 'X' AND stat  = 'I0002' )
    AND NOT EXISTS ( SELECT * FROM jest WHERE objnr = aufk~objnr AND  inact NE 'X' AND stat  = 'I0045' ).

5)、where 条件把空的range table放在后面,尽量按照index的先后循序摆放条件,<>、>、<、等条件最好放在后面,

6)、避免使用动态表名,动态字段名,避免使用distinct函数,

7)、强制使用索引%_hints_db6

8)、某些时候使用游标,或者native sql代替open sql,游标优点:可以直接对sql的每一条数据进行操作,而且可以使用for all entries in 和 open sql的range table,native sql,需要用perform 实现数据的操作,而且where条件不可以太复杂。

  data:cur type cursor.

  open cursor cur for select werks matnr aufnr menge meins bwart lgort from mseg
                                                               where werks in s_werks
                                                                 and bwart in ('551','552','951','952','201','202')
                                                                 and budat_mkpf in s_lfgja.
  do.
    fetch next cursor cur
    into ls_itab_mseg.
    if sy-subrc <> 0.
      close cursor cur.
      exit.
    else.
    endif.
  enddo.
EXEC SQL PERFORMING loop_output .
  select mandt, werks, vn_code, oa_code
    into :ls_para
    from ymsp_sup_para
    where werks in ('PSC1','PSD1')
ENDEXEC.

loop at lt_para into ls_para.
  write: / ls_para-mandt, ls_para-werks , ls_para-vn_code ,ls_para-oa_code.
endloop.

注:游标和native sql在使用的时候一定要声明client,否则会cross client。

3、内表操作:

1)、数据大的内表在使用结束之后,注意clear,减少内存

2)、善于利用和使用standard table、sorted table、hash table,hash在by key索引的时候效率最高,但是不能够append等操作,sorted table配合binary search效率上也还可以,但是同样不适合append 等操作,stardard table + sort + binary search效能上也比较客观,但是可以的话stardard table + secondary key效能更佳( 一个stardard table可以存在多种secondard key的排放形式 )

TYPES:BEGIN OF ts_prctr,
     vgbel  LIKE lips-vgbel,
     vgpos  LIKE lips-vgpos,
     prctr  LIKE vbap-prctr,
     pctrf  LIKE vbap-pctrf,
    kwmeng  LIKE vbap-kwmeng,
     flag   TYPE c,  "hans add 20180330
    END OF ts_prctr.
DATA:lt_prctr TYPE STANDARD TABLE OF ts_prctr
      WITH UNIQUE SORTED KEY z1 COMPONENTS vgbel vgpos,
      ls_prctr TYPE ts_prctr.

    READ TABLE lt_prctr WITH TABLE KEY z1 COMPONENTS vgbel = <fs_detail>-vgbel
                                                     vgpos = <fs_detail>-vgpos INTO ls_prctr.

注:此时的系统变量sy-tabix不可用。

3)、loop循环的嵌套使用时:内部table需要定义为sorted table或者standard table + sort的形式,loop + read + loop from sy-tabix

  LOOP AT it_matnr.
          read table lt_bom with key werks = it_matnr-werks  lead_matnr = it_matnr-matnr TRANSPORTING NO FIELDS BINARY SEARCH.
          if sy-subrc = 0.
            loop at lt_bom INTO ls_bom FROM sy-tabix.
              IF ls_bom-werks <> it_matnr-werks OR ls_bom-lead_matnr <> it_matnr-matnr.
                EXIT.
              ENDIF.
            endloop.
          endif.
  ENDLOOP.

4)、loop 的时候需要做modify ,可以用指针代替work area,

5)、read table trasporting no field / field_name可以提高效率

6)、loop 里面不要做delete,使用del_flag,然后批量操作

4、要使用好collect等函数

5、调用类方法快于function 函数,调用宏快于perform,

对于S4 HANA来说,HANA的计算能力十分强大,所以对于因为SQL运算引起的复杂计算导致的效能问题都可以通过 CDS View或者 HANA Calculation View来代替,Open SQL,这样CDS 或者CV他们在程序runtime的时候才会执行,计算能力比Open SQL要强大的多。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值