从内部 table 填充范围 table,不重复

Fill range table from internal table without duplicates

我想知道什么通常更快:

我想这可能是第一个,但我不知道 -
如何在我的代码中漂亮高效地集成删除重复项?

DATA:
  lt_itab       TYPE TABLE OF string,
  lt_range_itab TYPE RANGE OF string
  .

* Populating itab with duplicates
* Can the following somehow become a neat one-liner? This is ugly!
APPEND '1'  TO lt_itab.
APPEND '2'  TO lt_itab.
APPEND '2'  TO lt_itab.
APPEND '3'  TO lt_itab.
APPEND '4'  TO lt_itab.
APPEND '4'  TO lt_itab.

*Populating range table from itab
*Should one remove the duplicates here for a performance boost in the upcoming select?
*If so - how?
*-------------------------------------------------------
lt_range_itab = VALUE #(
  FOR <ls_itab> IN lt_itab
  ( sign = 'I'
    option = 'EQ'
    low = <ls_itab> )
).

*...or is such a select usually faster than the time it takes to remove the duplicates?
*-------------------------------------------------------
*SELECT *
*  FROM       anyTable
*  INTO TABLE @DATA(lt_new_data)
*  WHERE      anyProperty NOT IN @lt_range_itab.

这么多问题...:-)

编辑:我在答案中的讨论后修改了这个答案

What's usually faster?

好的数据库会 select 快速,即使范围内有 一些 重复项。 。相比之下,SAP HANA 可能会变慢,但其基于字典的架构通常会将其保持在可以忽略不计的水平。所以一般来说,我认为没有必要在每次查询之前删除重复项。

但是,如果优化器不是最优的并且存在大量重复,事情可能会出错。因此,如果您预期 重复,最好保持安全并在查询之前将其删除。

另请注意范围表有长度限制。它们被翻译成带有 IN 子句的 SQL 语句,并且 SQL 语句字符串具有最大字符数。因此,重复删除可能是使查询正常工作的必要策略。

可以将更长的范围转换为 FOR ALL ENTRIES,这会将查询打包并允许更长的范围。但是,该语句形式会导致与数据库的多次往返,并且 肯定会 遭受查询中的重复。

Can the following somehow become a neat one-liner?

DATA(lt_itab) = VALUE string_table( ( `1` ) ( `2` ) ( `2` ) ( `3` ) ( `4` ) ( `4` ) ).

或按照下面 Sandra 的建议立即进行:

SELECT ... WHERE anyProperty NOT IN ('1','2','3','4')

If so - how?

SORT lt_range_tab.
DELETE ADJACENT DUPLICATES FROM lt_range_tab.

最后但同样重要的是, 请注意,anyProperty IN @lt_range_tab 可能比相反的 NOT IN 变体快得多。数据库倾向于保留 positive 索引,这些索引对积极的查询反应最好。如果你有可能,例如因为您正在过滤具有固定值列表的字段,所以在将其发送到数据库之前反转过滤器可能是值得的。

第一个当然更快,因为物理磁盘的数据库操作比内存操作慢得多。

对性能的影响是否明显是另一个问题;这取决于重复选择的数量和数据量。

一个众所周知的例子是 SELECT ... FOR ALL ENTRIES 结构,如果不删除重复项,它会对性能产生很大影响,因为 ABAP 在内部将其转换为多个 SELECT,因此相同的数据可以选择多次(之后在ABAP端删除)。

简而言之,除非您确定数据量很小,否则请确保SELECT之前没有重复。