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 数据库,table1
和 table2
都是大约 2.5 亿行,table3
是大约 100 万行,combined
少于 1000 行。
SQL 优化器在“裸”表上比在“计算”表上有更多的信息。因此,更容易优化两个 CTE。
在使用索引的数据库中,这可能会影响索引的使用。在 Redshift 中,这可能会导致额外的数据移动。
不过,在这种特殊情况下,我怀疑问题可能与通过 JOIN
操作进行过滤有关。 UNION
会产生开销以删除重复项。通过过滤 before the UNION
,去重比事后过滤更快。
此外,UNION
可能会影响数据所在的位置,因此第二个版本可能需要额外的数据移动。
我有一个 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 数据库,table1
和 table2
都是大约 2.5 亿行,table3
是大约 100 万行,combined
少于 1000 行。
SQL 优化器在“裸”表上比在“计算”表上有更多的信息。因此,更容易优化两个 CTE。
在使用索引的数据库中,这可能会影响索引的使用。在 Redshift 中,这可能会导致额外的数据移动。
不过,在这种特殊情况下,我怀疑问题可能与通过 JOIN
操作进行过滤有关。 UNION
会产生开销以删除重复项。通过过滤 before the UNION
,去重比事后过滤更快。
此外,UNION
可能会影响数据所在的位置,因此第二个版本可能需要额外的数据移动。