使用 7.40+ 语法针对另一个 itab 值过滤 itab 的高性能方法?

问题描述

假设我有 2 个内部表:

TYPES:BEGIN OF LTY_FILE,SOKEY TYPE CHAR5,SOPONO TYPE CHAR15,SOCONO TYPE CHAR15,FLAG TYPE C,END OF LTY_FILE.
data:IT_ARCHIVE TYPE TABLE OF LTY_FILE,IT_SAP     TYPE TABLE OF LTY_FILE.
it_archive = VALUE #(
    ( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' )
    ( sokey = 'Key2' sopono = 'PO#34' socono = 'Four'  flag = 'B' ) ).
it_sap = VALUE #(
    ( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' ) ).

IT_ARCHIVE

SOKEY SOPONO SOCONO FLAG
Key1 PO#12 三个 A
Key2 PO#34 B

IT_SAP

SOKEY SOPONO SOCONO FLAG
Key1 PO#12 三个 A

现在我想要添加 IT_ARCHIVE 中不存在于 IT_SAP 中的基于键 SOKEYSOPONOSOCONO 的行使用 IT_SAPFLAG = D

SOKEY SOPONO SOCONO FLAG
Key2 PO#34 B

因此,新的 IT_SAP 应该如下所示:

SOKEY SOPONO SOCONO FLAG
Key1 PO#12 三个 A
Key2 PO#34 D

到目前为止,我尝试了以下方法,但在 ABAP 7.4 中失败了,但由于数据非常庞大(每次运行超过 400K),我正在寻找以性能为中心的代码来实现这一点。

DATA(ls_wa) = it_sap[ 1 ].  " Temporary workarea for insertion.
CLEAR:ls_wa  
LOOP AT IT_ARCHIVE ASSIGNING FIELD SYMBOL(<lfs_archive>).
   IF NOT LINE_EXISTS( it_sap[  sokey = <lfs_Archive>-sokey
                                sopono = <lfs_Archive>-sopono
                                socono = <lfs_archive>-socono ] ).

      ls_wa = <lfs_archive>.
      ls_wa-flag = 'D'.
      APPEND ls_wa to IT_SAP.
      CLEAR:ls_wa.
   ENDIF.
ENDLOOP.

我尝试的第二种方法:

  data(LT_FINAL) = IT_SAP[].
  REFRESH:LT_FINAL[].
  lt_final = VALUE #( FOR ls_ar IN IT_ARCHIVE
                          FOR ls_sap IN IT_SAP WHERE ( sokey <> <lfs_Archive>-sokey
                                                       sopono <> <lfs_Archive>-sopono
                                                       socono <> <lfs_archive>-socono )
                        ( 
                          "Explicitly mentioning all fields as have to change FLAG value
                            sokey = ls_Ar-sokey
                            sopono = ls_ar-sopono
                            socono = ls_ar-socono
                            flag = 'D'
                         ) ).

第一种方法需要太多时间,因为数据量很大。令我惊讶的是,第二种方法给我的结果与第一种不同。

ABAP 7.4+ 中是否有更好的方法来实现这一点?

解决方法

您的主要问题是关于性能的。有关信息,Stack Overflow 中还有其他关于性能和内部表的类似问题/答案。

在您的情况下,您使用“标准”表类型 (DATA ... TYPE TABLE OF ...),因此每次查找 (line_exists) 都会查看内部表的所有行,直到找到一行。与其一遍又一遍地查看所有行,最好将内表排序一次,每次查找都会快很多;这很容易理解为什么:如果你,人类,看字典(书)中的一个词,希望这些词被排序,你会很快找到这个词(前提是你知道字母 A、B、C 等的顺序) .; 电脑也是一样。

内表排序有两种方式:

  • 隐式地,通过将​​其声明为“已排序”或“散列”内部表,并且内部表的任何初始化或更改都将自动更新索引。
  • 或者明确地,通过语句 SORT。此选项更易于理解,但强烈建议尽可能不要使用。

要在排序和散列(即隐式排序)之间进行选择,您必须简单地知道是否可能有两行具有完全相同的键。

在您的情况下,只需执行下面的声明即可显着提高您当前(工作)算法的性能:

TYPES:BEGIN OF lty_file,sokey  TYPE char5,sopono TYPE char15,socono TYPE char15,flag   TYPE c,END OF lty_file.
TYPES:lty_file_tab TYPE SORTED TABLE OF lty_file WITH NON-UNIQUE KEY sokey sopono socono.
DATA:it_archive TYPE lty_file_tab,it_sap     TYPE lty_file_tab.

您还可以通过使用内置运算符 FILTER 来改进您的算法,我认为它在内核中运行得更多(有关 FILTER 的更多信息在其他 {{3 }}).

例如:

it_sap = VALUE #(
    BASE it_sap
    ( LINES OF VALUE #( FOR <line> IN
                            FILTER #( it_archive EXCEPT IN it_sap
                                    WHERE sokey  = sokey
                                      AND sopono = sopono
                                      AND socono = socono )
                        ( VALUE #( BASE <line> flag = 'D' ) ) ) ) ).

ASSERT it_sap = VALUE lty_file_tab(
    ( sokey = 'Key1' sopono = 'PO#12' socono = 'Three' flag = 'A' )
    ( sokey = 'Key2' sopono = 'PO#34' socono = 'Four'  flag = 'D' ) ).

(注意:我在这里使用 ASSERT 只是为了证明内部表具有指示的值;否则会停止程序/引发运行时错误)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...