【问题标题】:Redshift SQL Optimization - UNION ALL and DISTINCTRedshift SQL 优化 - UNION ALL 和 DISTINCT
【发布时间】:2021-11-23 00:03:55
【问题描述】:

假设我有一张容量很大的桌子。以下哪项会更优化?

SELECT DISTINCT shipping_address_id AS address_id FROM table_A
UNION
SELECT DISTINCT billing_address_id AS address_id FROM table_A

对比

SELECT DISTINCT address_id FROM
(
SELECT shipping_address_id AS address_id FROM table_A
UNION ALL 
SELECT billing_address_id AS address_id FROM table_A
)

【问题讨论】:

  • 当您在系统中对它们进行基准测试时,哪个表现更好?

标签: sql amazon-redshift query-optimization


【解决方案1】:

我相信你应该使用:

SELECT DISTINCT shipping_address_id AS address_id FROM table_A
UNION
SELECT DISTINCT billing_address_id AS address_id FROM table_A

这个自然更容易,因为它包含的字符更少(对文件更有用)并且更易于阅读(你想知道它的含义)。

【讨论】:

  • 谢谢!但是从性能的角度来看,这个可读性更强的版本是否也更好?
  • 是的,这样您就不会挠头,说“这到底是什么意思?”当你忘记它时。
【解决方案2】:

根据唯一地址占总地址的百分比,您可以发现 GROUP BY 的性能会更好。如果百分比很高,通常是实现唯一性的更好方法。试试:

SELECT address_id FROM
(
  SELECT shipping_address_id AS address_id FROM table_A
  UNION ALL 
  SELECT billing_address_id AS address_id FROM table_A
)
GROUP BY address_id;

此外,UNION(与 UNION ALL 相比)可能会很慢,并且运行 3 个不同的操作会让我相信这将是性能最差的。让我们知道哪个最好,我喜欢看到真实的实验数据结果。

【讨论】:

  • 我认为使用 DISTINCT 和 GROUP BY 没有任何区别;系统将对两者使用相同的查询计划。从可读性的角度来看,我倾向于说 DISTINCT 更好。从维护的角度来看,我也会这么说,因为我不必重复所涉及的字段列表(因此有出错的风险)
  • 几年前(总是为代码更改留出空间)当数据集很大并且不同值的数量很高时,使用 GROUP BY 生成不同结果时,Redshift 会执行得更快。如果不同值的数量较少,则 DISTINCT 更快。截至 2018 年,Redshift 肯定对这两种 SQL 模式进行了不同的优化。
【解决方案3】:

与所有 SQL 一样,唯一正确的答案是:“这取决于。”

您必须记住,对于(如果不是全部的话)大多数 SQL 实现,系统会返回您所要求的信息,但您无法真正说明它应该如何为您提供这些信息。查询优化器将查看您的查询,查看可用数据(通过统计信息)、可用索引、可用资源等,并提出如何以最有效的方式获取数据的计划.

因此,很可能两个看起来完全不同的查询仍然会导致在后面执行相同的查询计划。或者两个相同的查询将导致执行完全不同的计划。 (例如,在测试中是这样的,因为你有 100 条记录,在生产中是这样的,因为你有数百万条记录)

您还需要知道 UNION 实际上是一个 UNION ALL 操作,后跟一个 DISTINCT 操作。

所以,如果你这样做:

SELECT DISTINCT address_id FROM
(
    SELECT shipping_address_id AS address_id FROM table_A
    UNION ALL 
    SELECT billing_address_id AS address_id FROM table_A
)

这其实和做的一样

SELECT shipping_address_id AS address_id FROM table_A
UNION 
SELECT billing_address_id AS address_id FROM table_A

您可以使用“EXPLAIN ANALYZE”运行查询来确认这一点。

在将两个 SELECT 合并在一起之前是否应该“预先区分”这两个 SELECT 的问题很棘手,可能取决于您的数据是什么样的。假设这两个字段都被索引,那么单独对它们进行 DISTINCT 可能会非常快,如果生成的(不同的)列表明显小于最初的列表,那么执行 2 + 1 个不同操作的开销可能比运行与组合列表不同。 但是,如果两个起始列表几乎都是唯一的(并且可能也没有索引),那么在整体上做 1 个大的不同可能会更快

结论:没有适合所有情况的1个答案;最好的办法是两者都试一下,看看哪种效果最好。解释分析是你的朋友。您将了解背景中发生的事情,并且凭借这些经验以及您对正在处理的(可能是预期的)数据的了解,应该可以帮助您决定如何进行。请记住,(过度)针对当前情况进行优化可能会在数据量可能大幅增加的 1 年内给您带来不利影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多