在 Redshift 中高效地加入和聚合大量事实表

我在 Redshift 中有许多(1000 万行)事实表,每个都有一个自然键 memberid,每个都有一个列 timestamp。假设我有三个表:transactionsmessagesapp_openstransactions 看起来像这样(所有其他表都具有类似的结构):

memberid 收入 时间戳
374893978 3.99 2021-02-08 18:34:01
374893943 7.99 2021-02-08 19:34:01

我的目标是创建一个像这样的每日 per-memberid 聚合表,每个 memberid 和日期都有一行:

memberid 日期 daily_revenue daily_app_opens daily_messages
374893978 2021-02-08 4.95 31 45
374893943 2021-02-08 7.89 23 7

我目前为此使用的 SQL 如下,其中涉及合并单独的子查询:

SELECT memberid,date,max(NVL(daily_revenue,0)) daily_revenue,max(NVL(daily_app_opens,0)) daily_app_opens,max(NVL(daily_messages,0)) daily_messages
FROM 
 (
 SELECT memberid,trunc(timestamp) as date,sum(revenue) daily_revenue,NULL AS daily_app_opens,NULL AS daily_messages
 FROM transactions
 GROUP BY 1,2

 UNION ALL

 SELECT memberid,NULL AS daily_revenue,count(*) daily_app_opens,NULL AS daily_messages
 FROM app_opens
 GROUP BY 1,count(*) daily_messages
 FROM messages
 GROUP BY 1,2
)
GROUP BY memberid,date

这工作正常并产生预期的输出,但我想知道这是否是执行此类查询的最有效方法。我也使用 FULL OUTER JOIN 代替 UNION ALL,但性能基本相同。

在 Redshift 中实现这一目标的最有效方法是什么?

zcshou 回答:在 Redshift 中高效地加入和聚合大量事实表

查看 EXPLAIN 计划会有所帮助,因为它可以让我们看到查询中成本最高的部分是什么。基于对 SQL 的快速阅读,它看起来相当不错。扫描事实表的成本可能很有意义,但这是您必须忍受的成本。如果您可以使用 where 子句限制读取的数据量,这可以减少,但这样做可能无法满足您的需求。

您应该查看的一个地方是这些表的分布。由于您是按 accountid 分组,将其作为分发密钥将使此过程更快。分组需要将相同 accountid 值的行放在一起,在这些值上分布将大大减少集群内的网络流量。

在大数据量和其他所有优化的情况下,我希望 UNION ALL 执行完全外部联接,但这将取决于许多因素(例如 accountid 聚合减少了多少数据大小)。 10M 行在 Redshift 术语中并不是很大(我在最小集群上有 160M 行宽数据)所以我认为在这些大小下这些计划之间不会有太大差异。

本文链接:https://www.f2er.com/59259.html

大家都在问