JOIN然后UNION与UNION然后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,或者至少不会影响执行时间。我很惊讶地发现查询现在要花几乎两倍的时间来运行。

这没问题,因为它在以前非常好用,我还是只是出于个人喜好改写了它,所以我会坚持使用原来的样式。但是我在数据库/ sql方面不是专家,所以我很想知道是否有人可以分享为什么第二种方法性能这么差的见解?

如果有所作为,那就是Redshift数据库table1table2约有2.5亿行,table3是约100万行,combined少于1000行。

解决方法

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

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

不过,在这种特殊情况下,我怀疑问题可能与通过JOIN操作进行过滤有关。 UNION的开销是删除重复项。通过在UNION之前过滤 ,重复删除比之后过滤更快。

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