3

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

DATA: wa_collectoraction TYPE zcollectoraction,
  it_collectoraction LIKE STANDARD TABLE OF zcollectoraction.

然后我在表格中填写:

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.

这个循环对 3000 条记录执行 5 分钟。有人可以告诉我该怎么做才能更快吗?  

提前致谢

4

4 回答 4

4

分析独立报告性能的最佳工具是 ST12,因此如果有机会,请跟踪它。
不知不觉中,我们不得不猜测,最大的问题要么是带有 subSELECT 的 SELECT,要么是 MODIFY。

1) LOOP 中的 SELECT 总是很慢

在这里,您实际上为it_collectoraction.

尝试减少 SELECT 的数量

根据具有相同 的行数,将 LOOP 中的 SELECT 替换为具有来自LOOP 外部的 FOR ALL ENTRIES 的 SELECT 并在 ABAP 端找到 MAX(time)dat可能会快得多。zcollectoraction

指数覆盖率

似乎还好。

2) MODIFY 在 STANDARD 表上很慢

您必须筛选整个表格才能找到相关行。如果定义it_collectoraction为 SORTED,这会快得多。如果在 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.
于 2017-10-03T12:19:30.010 回答
3

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

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

让我知道您是否需要更多详细信息。

于 2017-10-04T03:41:21.937 回答
0

首先,我要感谢大家的帮助。我根据用户的选择数据,通过使用包含来自 dbtab 的所有记录的内部表来更改选择的逻辑。于是代码变成了如下:

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。在第一个 10 秒内,它处理 14.000 条记录。在 1 分钟的过程中 38.500 和在 1 分钟和 50 秒内完成了 54.500 条记录。它给我的印象是它完成了某件事,从而减慢了进程。任何想法?

于 2017-10-04T10:53:19.323 回答
-1

我参加聚会有点晚了,但是我在您的第一篇文章中看到的是,您只想从每个 bukrs 和 kunnr 的一个表中读取最新的(最大(日期)和最大(时间))条目?

使用一个选择来获取表格的内容。仅按关键字段或索引选择:我假设日期不是关键字段,而是 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.
于 2017-10-05T08:10:17.363 回答