【问题标题】:Fill range table from internal table without duplicates从内部表中填充范围表而不重复
【发布时间】:2018-08-17 09:45:04
【问题描述】:

我想知道什么通常更快:

  • 过滤掉重复项,然后进行选择
  • 直接选择重复项

我认为它可能是第一个,但我不知道 -
如何在我的代码中很好地有效地集成删除重复项?

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.

【问题讨论】:

    标签: performance abap


    【解决方案1】:

    这么多问题... :-)

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

    什么通常更快?

    即使该范围内有 一些 个重复项,好的数据库也会快速选择。 Oracle's optimizer, for example, removes duplicates on its own。相比之下,SAP HANA 可能会变得更慢,但其基于字典的架构通常会将其保持在可以忽略不计的水平。所以一般来说,我认为没有必要在每次查询之前删除重复项。

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

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

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

    以下内容能否以某种方式成为整洁的单行字?

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

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

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

    如果是这样 - 怎么做?

    SORT lt_range_tab.
    DELETE ADJACENT DUPLICATES FROM lt_range_tab.
    

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

    【讨论】:

    • 谢谢,很抱歉有很多问题!这个答案正是我所希望的!
    • 1) 我不同意“无需删除重复项”,我在单独的答案中解释了为什么 2) 这篇文章是也可以SELECT ... WHERE anyProperty NOT IN ('1','2','3','4'),或者如果您愿意,也可以使用常量而不是文字(PS:我同意不应该作为经验法则来避免,但是数据库可以很好地处理它-取决于许多参数-,所以如果没有其他选择,那么性能测试将确认它是否可以)
    • Sandra 对于所有参赛作品绝对是正确的。这可能会导致与数据库的额外往返并降低性能。但是范围会导致 IN 子句 - 这是非常不同的。它们是否更慢取决于优化器。 SAP HANA 不会因为它的字典架构而变慢。 Oracle 的数据库也没有,由于其强大的优化器,请考虑stackoverflow.com/questions/37666282/…
    • 性能还可以,但是由于查询的最终最大长度(始终取决于数据库),您仍然需要减小 IN 值的大小,因此仍然要删除重复项。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 绝对同意!使用sort + delete adjacent duplicates => 我曾经(由于排序函数的错误)有一个包含数万个条目的输入表,其中只有几个(少于 10 个)不同 => 产生了巨大的差异!!!
    猜你喜欢
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2013-11-07
    • 2018-07-20
    • 2020-01-07
    • 2016-02-29
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多