JOIN then UNION vs. UNION then JOIN 的性能

Performance of JOIN then UNION vs. UNION then JOIN

我有一个 SQL 查询如下:

WITH a AS (
    SELECT *
    FROM table1
        INNER JOIN table3 ON table1.id = table3.id
    WHERE table1.condition = 'something'
),

b AS (
    SELECT *
    FROM table2
        INNER JOIN table3 ON table2.id = table3.id
    WHERE table2.condition = 'something else'
),

combined AS (
    SELECT *
    FROM a
    UNION
    SELECT *
    FROM b
)

SELECT *
FROM combined

我将其重写为:

WITH a AS (
    SELECT *
    FROM table1
    WHERE table1.condition = 'something'
),

b AS (
    SELECT *
    FROM table2
    WHERE table2.condition = 'something else'
),

combined AS (
    SELECT *
    FROM (
        SELECT *
        FROM a
        UNION
        SELECT *
        FROM b
    ) union
    INNER JOIN table3 ON union.id = table3.id
)

SELECT *
FROM combined

我预计这可能会更高效,因为它只执行一次 JOIN,或者至少不会影响执行时间。我惊讶地发现查询现在花费的时间几乎是 运行.

的两倍

这没问题,因为它以前工作得很好,无论如何我只是出于个人风格偏好重写了它,所以我会坚持原来的。但我不是 databases/SQL 方面的专家,所以我很想知道是否有人可以分享任何关于为什么第二种方法性能如此差的见解?

如果有区别的话,它是一个 Redshift 数据库,table1table2 都是大约 2.5 亿行,table3 是大约 100 万行,combined 少于 1000 行。

SQL 优化器在“裸”表上比在“计算”表上有更多的信息。因此,更容易优化两个 CTE。

在使用索引的数据库中,这可能会影响索引的使用。在 Redshift 中,这可能会导致额外的数据移动。

不过,在这种特殊情况下,我怀疑问题可能与通过 JOIN 操作进行过滤有关。 UNION 会产生开销以删除重复项。通过过滤 before the UNION,去重比事后过滤更快。

此外,UNION 可能会影响数据所在的位置,因此第二个版本可能需要额外的数据移动。