【问题标题】:Optimizing JOIN ON OR without repeating query for every OR优化 JOIN ON OR 而不对每个 OR 重复查询
【发布时间】:2015-08-19 00:11:55
【问题描述】:

正如this answer 解释的那样,JOIN ONOR 结合使用无法优化。我确实注意到我正在尝试编写的查询中的可怕性能。

为了描述我的场景,应该返回一个标题记录以及来自所有相关项目记录的数据。项目可以基于三个字段之一与标题记录相关。下面的 SQL 在语法上看起来很合理,但由于无法优化 JOIN ON OR,因此代价高昂:

SELECT
    header.a,
    header.b,
    item.x,
    item.y,
    item.z
    FROM header
    LEFT OUTER JOIN item    ON item.x   = header.a
                            OR item.y   = header.a
                            OR item.z   = header.b;

请注意,这是从一个复杂得多的查询中概括出来的(涉及另外 6 个连接和各种过滤器)。我预计JOIN ON OR 实现将起作用,尽管我无法确认它,因为OR 导致的全表扫描可能需要几个小时才能完成。 (额外的问题:三重条件会导致单个连续的 FTS 还是三个连续的 FTS?)

由于周围查询的复杂性,我想避免链接答案中建议的 UNION ALL 方法。这不仅是因为我想避免这种级别的重复,而且查询的其余部分虽然经过优化,但本身就非常昂贵。有没有我没有看到的替代方案?

【问题讨论】:

  • 您使用的是哪个 dbms? (不同的产品以不同的方式优化事物......)
  • @jarlh 我们在 SAP HANA(SQL 脚本)上运行。
  • item 表有多少列?
  • @gotqn 大约 70 个。我选择了其中的 8 个。如果相关,它是一个列存储。
  • @Lilienthal 我不熟悉hana,但在t-sql 中,您可以使用included 列创建额外的filtering 索引,这可以优化性能,减少read 操作。跨度>

标签: sql join optimization hana


【解决方案1】:

这可能看起来很难看,但它避免了 OR,并且有机会使用索引(如果存在):

SELECT
    header.a
    , header.b
    , COALESCE(i1.x, i2.x, i3.x) AS itemx
    , COALESCE(i1.y, i2.y, i3.y) AS itemy
    , COALESCE(i1.z, i2.z, i3.z) AS itemz
    FROM header h0
    LEFT OUTER JOIN item i1 ON i1.x = h0.a
    LEFT OUTER JOIN item i2 ON i2.y = h0.a
    LEFT OUTER JOIN item i3 ON i3.z = h0.b
        ;

注意:它确实假定 item.{x.y,z} 不可为空

【讨论】:

  • 嗯,非常有趣的方法,这可能是一个很好的单查询解决方案。直到几天后,我才能为我的方案验证这一点,但这在理论上看起来是合理的,+1。
  • 在 SQL 编辑器中确认。 COALESCE 的 SAP HANA 文档条目是 here。我不得不将另一个表加入到似乎与 INNER JOIN subitem ON subitem.key = COALESCE(i1.key, i2.key, i3.key) 一起使用的项目表中
  • 注意:ON xxx = COALESCE(a,b,c, ...) 仍然存在多个 -OR JOIN 问题(但形式不同)检查您的查询计划;它可能非常不太理想。还要验证 NULLability(如果 {x,y,z} 是 NULLable,查询可能会产生错误的结果)
  • 同意,我的查询肯定仍在进行中,我正在评估 COALESCE 是否会(有效地)适用于我的特定场景。也就是说,这个解决方案适用于核心问题,因此接受。
  • 我不知道 HANA 的查询生成器,但是让 OR'red UNION 更明确会有所帮助。
【解决方案2】:

虽然我认为您的整体查询中存在大量复杂性,但我建议拆分此执行并在这种情况下实际使用 SQLScript。

由于您实际上有三种不同的方式来关联标题和项目,因此产生了三个查询。 使用 SQLScript,将这三个简单的连接查询分配给三个单独的表变量是相当简单的。

然后可以非常有效地处理这些连接中的每一个,并且可以同时执行所有三个连接。这不会减少整体工作量,而是减少总执行时间。

此外,根据查询的性质,您可以合并三个表变量并将它们用作复杂剩余计算的输入。

无论如何:这是您的表之间的三个独立链接,不尝试将它们塞进一个“所有 SQL 之母”语句中似乎是最优雅和最有效的 :-)

【讨论】:

  • 嗯,好点子,我可能会走这条路,因为我在尝试创建一些可怕的单个 SQL 语句时确实碰壁了。我假设我会将该 SQL 脚本实现为 ABAP 托管数据库过程?
  • 如果您在 ABAP 上运行,那就是这样。
猜你喜欢
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 1970-01-01
  • 2021-04-05
  • 2021-06-08
相关资源
最近更新 更多