从内部 table 填充范围 table,不重复
Fill range table from internal table without duplicates
我想知道什么通常更快:
- 过滤掉重复项,然后执行 select
或
- 直接用重复的
做select
我想这可能是第一个,但我不知道 -
如何在我的代码中漂亮高效地集成删除重复项?
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之前没有重复。
我想知道什么通常更快:
- 过滤掉重复项,然后执行 select
或 - 直接用重复的 做select
我想这可能是第一个,但我不知道 -
如何在我的代码中漂亮高效地集成删除重复项?
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 快速,即使范围内有 一些 重复项。
但是,如果优化器不是最优的并且存在大量重复,事情可能会出错。因此,如果您预期 重复,最好保持安全并在查询之前将其删除。
另请注意范围表有长度限制。它们被翻译成带有 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之前没有重复。