优化 JOIN ON OR 而无需为每个 OR 重复查询

Optimizing JOIN ON OR without repeating query for every OR

正如 this answer 所解释的那样,无法优化 JOIN ONOR 的组合。我确实注意到我正在尝试编写的查询中的糟糕性能。

为了描述我的场景,应该返回一条 header 记录以及来自所有相关项目记录的数据。一个项目可以与基于三个字段之一的 header 记录相关。下面的 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 产生的完整 table 扫描可能需要几个小时才能完成。 (奖金问题:三重条件会导致单个连续 FTS 还是三个连续 FTS?)

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

虽然我明白你的观点是在整个查询中有很多复杂性,但我建议拆分此执行并在这种情况下实际使用 SQLScript。

由于您有效地使用三种不同的方式来关联 header 和项目,因此进行了三个查询。 使用 SQLScript,将这三个简单的连接查询分配给三个单独的 table 变量是相当简单的。

这些连接中的每一个都可以非常有效地处理,而且它们三个都可以同时执行。这不会减少整体工作,但会减少总执行时间。

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

在任何情况下:这些是您的 table 之间的三个独立链接,不试图将它们塞进一个 "mother of all SQL" 语句中似乎是最优雅和最有效的:-)

这可能看起来很丑陋,但它避免了 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} 不可为空.