在 WHERE 中使用条件 =、>=、<= 优化 LOOP AT

Optimize LOOP AT with conditions =, >=, <= in WHERE

我的内部 table 包含大量数据。

我有以下代码:

LOOP AT lt_tab INTO ls_tab
  WHERE value1 EQ lv_id1
    AND value2 LE lv_id2
    AND value3 GE lv_id3.

  IF ls_tab-value4 IS NOT INITIAL.
    IF ls_tab-value4 NE lv_var.
      lv_flag = lc_var.
      EXIT.
    ENDIF.
  ELSE.
    lv_flag = lc_var.
    EXIT.
  ENDIF.
ENDLOOP.

数据库table包含7个字段,内部table与数据库table具有相同的类型。

where 子句中没有主键字段。

table中有一个组合键,由两个主键组成。 table 字段是 transid(主键)、item1(主键)、value1value2value3value4.

我必须仅根据这些条件搜索 table。但这花费了太多时间。如何优化?

您可以使用 LOOP AT ... ASSIGNING (<fieldsymbol>)。 赋值比 LOOP AT ... INTO structure 更高效。 Here 更多信息。

虽然您没有提供足够的信息来完全确定真正的问题是什么,但可以假设您遇到的性能问题是因为您在循环条件中使用了非关键字段.

LOOP AT lt_tab INTO ls_tab
  WHERE value1 EQ lv_id1
    AND value2 LE lv_id2 
    AND value3 GE lv_id3.

您可以为变量 lt_tab 的 table 类型定义一个 secondary sorted key,它将包含字段 value1value2value3.

看看下面的例子。

REPORT zzy.

CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-METHODS:
      class_constructor,
      main.
  PRIVATE SECTION.
    TYPES: BEGIN OF t_record,
      transid TYPE sy-index,
      item1   TYPE char20,
      value1  TYPE p LENGTH 7 DECIMALS 2,
      value2  TYPE p LENGTH 7 DECIMALS 2,
      value3  TYPE p LENGTH 7 DECIMALS 2,
      value4  TYPE p LENGTH 7 DECIMALS 2,
    END OF t_record,
    tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1.
*    tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1
*          WITH UNIQUE SORTED KEY sec_key COMPONENTS value1 value2 value3.
    CONSTANTS:
      mc_value1 TYPE p LENGTH 7 DECIMALS 2 VALUE '100.00',
      mc_value2 TYPE p LENGTH 7 DECIMALS 2 VALUE '150.00',
      mc_value3 TYPE p LENGTH 7 DECIMALS 2 VALUE '10.0'.
    CLASS-DATA:
      mt_record TYPE tt_record.
ENDCLASS.

CLASS lcl_main IMPLEMENTATION.
  METHOD class_constructor.
    DO 2000000 TIMES.
      INSERT VALUE t_record( transid = sy-index item1 = |Item{ sy-index }| 
            value1 = sy-index value2 = sy-index / 2 value3 = sy-index / 4 value4 = 0 )
        INTO TABLE mt_record.
    ENDDO.
  ENDMETHOD.

  METHOD main.
    DATA:
      l_start TYPE timestampl,
      l_end   TYPE timestampl,
      l_diff  LIKE l_start.
    GET TIME STAMP FIELD l_start.
    LOOP AT mt_record INTO DATA(ls_record) "USING KEY sec_key
      WHERE value1 = mc_value1 AND value2 >= mc_value2 AND value3 <= mc_value3.

      ASSERT 1 = 1.

    ENDLOOP.
    GET TIME STAMP FIELD l_end.
    l_diff = l_end - l_start.

    WRITE: / l_diff.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_main=>main( ).

如果table类型tt_record定义如下

tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1.

那么我的 SAP 系统上的 运行 循环时间从 0.1560.266 秒不等。

如果您按如下方式定义它

tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1
      WITH UNIQUE SORTED KEY sec_key COMPONENTS value1 value2 value3.

并通过添加提示 USING KEY sec_key 来调整循环然后我每次得到的 运行 时间是 0.00.

如果你有很多数据,让一行代码快一点也无济于事。

问题可能是您正在进行全面 table 扫描。您正在处理 table 的每一行(直到找到您要搜索的内容)

对于这类问题,有排序的tables和散列的tables:

http://help.sap.com/saphelp_nw70/helpdata/en/fc/eb366d358411d1829f0000e829fbfe/content.htm

如果你明智地使用它们,select 只需检查 table 中的一小部分行,这会导致大量更快的 selection,具体取决于分布table.

中的数据

在这种情况下,我们需要 SORTED 内部 table 而不是 STANDARD 内部 table(默认行为) 以提高海量数据情况下的性能。

内部定义示例table

DATA: lt_sorted_data TYPE SORTED TABLE OF TABLENAME WITH NON-UNIQUE KEY MTART.

在你的情况下,因为 TABLENAME 已经是一个数据库 table,它已经包含一个主键,我们需要创建另一个(本地)结构相同的列列表,并通过

加载数据
select * into CORRESPONDING FIELDS OF TABLE lt_sorted_data

然后在log(n)基础上会更快。

对于此处的内部 table "lt_tab",我将使用 ABAP Sorted table 以及您在该循环语句的 Where 条件中使用的键。

另外,如果这个循环已经在另一个循环下使用 比我强烈建议你检查术语 "Partially sequential set access" 它在性能循环上产生了很大的差异。这在您使用排序表时有效。

你可以为此使用二进制循环算法...

  • 按主键
  • 对内部 table 进行排序
  • 使用您需要的密钥通过二进制搜索进行阅读。存储索引 (sy-tabix)。
  • 从索引 XX 开始在内部 table 循环。
  • 此时主键发生变化(在循环内检查),退出循环即可。

您可以仅使用您的唯一密钥来执行密钥 table 的内部循环。性能优化了很多这样做。 我希望这有帮助。