非常缓慢的itab循环

时间:2017-10-03 10:30:48

标签: sap abap

我已经声明了一个内部表格,如:

SELECT bukrs kunnr yearmonth MAX( dat ) AS dat
FROM zcollectoraction
  INTO CORRESPONDING FIELDS OF TABLE it_collectoraction
WHERE bukrs IN so_bukrs AND
      kunnr IN so_kunnr AND
      dat   IN so_date
GROUP BY bukrs kunnr yearmonth.

然后我填写表格:

LOOP AT it_collectoraction INTO wa_collectoraction.
PERFORM progress_bar USING 'Retrieving data...'(035)
                           sy-tabix
                           i_tab_lines.
"Get the MAX TIME for all lines in order to cover the case we have more than 1 line."
SELECT SINGLE * FROM zcollectoraction
    INTO CORRESPONDING FIELDS OF wa_collectoraction
  WHERE bukrs = wa_collectoraction-bukrs AND
        kunnr = wa_collectoraction-kunnr AND
        dat   = wa_collectoraction-dat   AND
        time  = ( SELECT MAX( time ) AS time
                    FROM zcollectoraction
                    WHERE bukrs = wa_collectoraction-bukrs AND
                          kunnr = wa_collectoraction-kunnr AND
                          dat   = wa_collectoraction-dat ).

MODIFY it_collectoraction FROM wa_collectoraction.
ENDLOOP.

最后我有以下循环

getUserLocationFromGPS()
.buffer(5 sec, 1 item) //not sure how to do this in rx-java
.map(x => { // this is select in .net
    if(x.IsEmpty)
      return getDefautLocation();
    else
      return x[0];
    }).Subscribe(...)

对于3000条记录,此循环正在进行5分钟。 有人可以告诉我该怎么做才能更快?

提前致谢

4 个答案:

答案 0 :(得分:4)

分析独立报告性能的最佳工具是ST12,所以如果有机会,请跟踪它。
我们不得不猜测,最大的问题是带有subSELECT的SELECT或MODIFY。

1)LOOP中的SELECT总是很慢

在这里,您实际为it_collectoraction中的每一行创建了两个。

尝试减少SELECT的数量

根据具有相同dat的行数,将LOOP中的SELECT替换为LOOP外zcollectoraction的SELECT FOR FOR ALL ENTRIES可能要快得多,并找到ABAP方面的MAX(时间)。

索引覆盖率

似乎没事。

2)STANDARD表

上的MODIFY很慢

你必须在整个表格中筛选才能找到相关的一行。如果将it_collectoraction定义为SORTED,则速度会快得多。如果在LOOP中使用字段符号,则可以完全避免。

编码

用这个替换您的LOOP:

TYPES: BEGIN OF tty_coll_act,
        bukrs TYPE burks,
        kunnr TYPE kunnr,
        dat   TYPE dat,
        time  TYPE time,
      END OF tty_coll_act.

DATA: lt_coll_act TYPE TABLE OF tty_coll_act,
      ls_coll_act LIKE LINE OF lt_coll_act.

FIELD-SYMBOLS: <fs_collectoraction> LIKE LINE OF it_collectoraction.

SELECT bukrs kunnr dat time
    INTO TABLE lt_coll_act
    FROM zcollectoraction
    FOR ALL ENTRIES IN it_collectoraction
    WHERE bukrs = wa_collectoraction-bukrs AND
          kunnr = wa_collectoraction-kunnr AND
          dat   = wa_collectoraction-dat.

SORT lt_coll_act BY bukrs kunnr dat time DESCENDING.

LOOP AT it_collectoraction ASSIGNING <fs_collectoraction>.
" the READ TABLE finds the first matching row,
" it will be MAX(TIME) as TIME is sorted descending       
  READ TABLE lt_coll_act INTO ls_coll_act
      WITH KEY  bukrs = <fs_collectoraction>-bukrs
                kunnr = <fs_collectoraction>-kunnr
                dat   = <fs_collectoraction>-dat BINARY SEARCH.
  <fs_collectoraction> = ls_coll_act.
ENDLOOP.

答案 1 :(得分:3)

不是在循环中添加选择查询,而是将所有数据放入内部表并使用循环内的read语句处理它。

在循环中添加选择查询将始终减慢应用程序的执行速度,因为应用程序必须为每个循环执行数据库查询。将所有必需的信息加载到内部表中,然后在应用程序中处理数据要快得多。

如果您需要任何进一步的详细信息,请与我们联系。

答案 2 :(得分:0)

首先,我要感谢你们所有人的帮助。 我根据用户的选择数据,使用包含dbtab中所有记录的内部表来更改select的逻辑。 所以代码如下:

DATA: wa_collectoraction TYPE zcollectoraction,
  it_collectoraction TYPE TABLE OF zcollectoraction,
  itsort_collectoraction TYPE HASHED TABLE OF zcollectoraction
      WITH UNIQUE KEY mandt bukrs kunnr yearmonth dat time.

FIELD-SYMBOLS: <fs_collectoraction> LIKE LINE OF it_collectoraction.

SELECT bukrs kunnr yearmonth MAX( dat ) AS dat
  FROM zcollectoraction
    INTO CORRESPONDING FIELDS OF TABLE it_collectoraction
  WHERE bukrs IN so_bukrs AND
        kunnr IN so_kunnr AND
        dat   IN so_date
  GROUP BY bukrs kunnr yearmonth.

" Keep the total records which will be inserted.
i_tab_lines = sy-dbcnt.

SELECT * INTO TABLE itsort_collectoraction
  FROM zcollectoraction
  WHERE bukrs IN so_bukrs AND
      kunnr IN so_kunnr AND
      dat   IN so_date.

SORT itsort_collectoraction
            BY mandt bukrs kunnr yearmonth dat time DESCENDING.

LOOP AT it_collectoraction ASSIGNING <fs_collectoraction>.
  PERFORM progress_bar USING 'Retrieving data...'(035)
                             sy-tabix
                             i_tab_lines.

  READ TABLE itsort_collectoraction INTO wa_collectoraction
      WITH KEY bukrs = <fs_collectoraction>-bukrs
                kunnr = <fs_collectoraction>-kunnr
                yearmonth = <fs_collectoraction>-yearmonth
                dat   = <fs_collectoraction>-dat.
  <fs_collectoraction> = wa_collectoraction.
ENDLOOP.

此代码在1分钟内运行43000条记录。 唯一的问题是,在第一个10000到15000个记录之后,该过程正在减慢。我不知道是否有任何要求清除的命令。我不知道该清楚什么。

再次感谢你们所有人。 问候 利亚

PS。在第1个10秒,它处理14.000个记录。     在1分钟的过程38.500和     1分钟&amp; 50秒完成了54.500条记录。   它给我的印象是,它实现了减慢过程的速度。任何的想法?

答案 3 :(得分:-1)

我参加派对有点晚了,但是我在你的第一篇文章中看到的是你只想阅读每个bukrs和kunnr的一张表中的最新(最大(日期)和最大(时间))条目? / p>

使用一个选择来获取表格的内容。仅按键字段或索引选择: 我假设日期不是关键字段,而是bukrs和kunnr:

SELECT bukrs kunnr yearmonth dat time
FROM zcollectoraction
  INTO CORRESPONDING FIELDS OF TABLE it_collectoraction
WHERE bukrs IN so_bukrs AND
      kunnr IN so_kunnr 
.

从itab中删除非关键字段:

DELETE it_collectoraction WHERE dat NOT IN so_date.

按日期和时间降序排序itab,以便最新条目是bukrs和kunnr的第一个组合

SORT it_collectoraction BY bukrs kunnr date DESCENDING time DESCENDING.

每个bukrs和kunnr删除所有相邻的(=在第一个之后具有相同比较键的所有条目)

DELETE ADJACENT DUPLICATES FROM it_collectoraction COMPARING bukrs kunnr.