我的内部表包含大量数据。
我有以下代码:
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.
数据库表包含7个字段,内部表与数据库表具有相同的类型。
在where子句中没有主键字段。
表中有一个由两个主键组成的组合键。表字段为transid
(主键)、item1
(主键),value1
、value2
、value3
和value4
。
我只能根据这些条件搜索表格。但这花了太多时间。如何优化它?
尽管您没有提供足够的信息来完全确定真正的问题是什么,但可以假设您遇到的性能问题是因为您在循环的条件中使用了非键字段。
LOOP AT lt_tab INTO ls_tab
WHERE value1 EQ lv_id1
AND value2 LE lv_id2
AND value3 GE lv_id3.
您可以为变量lt_tab
的表类型定义一个辅助排序键,该键将包含字段value1
、value2
和value3
。
看看下面的例子。
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( ).
如果表类型tt_record
以以下方式定义
tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1.
则循环在我的SAP系统上的运行时间从CCD_ 12到CCD_。
但是,如果您将其定义为以下
tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1
WITH UNIQUE SORTED KEY sec_key COMPONENTS value1 value2 value3.
并通过添加提示CCD_ 14来调整循环,则我每次获得的运行时间为CCD_。
在这种情况下,我们需要一个SORTED内部表,而不是STANDARD 内部表格定义示例 在您的情况下,由于TABLENAME已经是一个数据库表,其中已经包含一个主键,我们需要创建另一个具有相同列列表的(本地)结构,并通过加载数据 然后在log(n)的基础上会更快。DATA: lt_sorted_data TYPE SORTED TABLE OF TABLENAME WITH NON-UNIQUE KEY MTART.
select * into CORRESPONDING FIELDS OF TABLE lt_sorted_data
您可以使用LOOP AT ... ASSIGNING (<fieldsymbol>)
。分配比LOOP AT ... INTO structure
更具性能。这里有更多信息。
如果你有很多数据,那么让一行代码更快一点也无济于事。
问题可能是您正在进行全表扫描。您正在处理表格的每一行(直到找到您要搜索的内容)
对于这类问题,有排序表和哈希表:
http://help.sap.com/saphelp_nw70/helpdata/en/fc/eb366d358411d1829f0000e829fbfe/content.htm
如果你明智地使用它们,选择只需要检查表中的一小部分行,这会导致更快的选择,这取决于表中数据的分布。
对于这里的内部表"lt_tab",我将使用一个ABAP排序表,其中包含您在循环语句的Where条件中使用过的键。
此外,如果此循环已在另一个循环下使用我强烈建议您检查术语"部分顺序集访问"它在性能循环上产生了很大的差异。当您使用"排序表"时,这会起作用。
您可以使用二进制循环算法来实现。。。
- 按主键对内部表进行排序
- 使用您需要的密钥进行二进制搜索。存储索引(sy-tabix)
- 在索引XX的内部表处循环
- 此时主键发生更改(在循环中检查),只需退出循环
您可以只使用唯一的键来执行键表的内部循环。这样做的性能优化了很多。我希望这能有所帮助。