Redshift 中的 DAU WAU MAU 错误:[Amazon](500310) 无效操作:由于内部错误,不支持此类关联子查询模式;

Posted

技术标签:

【中文标题】Redshift 中的 DAU WAU MAU 错误:[Amazon](500310) 无效操作:由于内部错误,不支持此类关联子查询模式;【英文标题】:DAU WAU MAU Error in Redshift: [Amazon](500310) Invalid operation: This type of correlated subquery pattern is not supported due to internal error; 【发布时间】:2021-02-09 12:59:07 【问题描述】:

我正在尝试计算 DAU WAU MAU 比率。

DAU:当天活跃用户数 WAU:过去 7 天的活跃用户 MAU:过去 30 天的活跃用户

DAU:WAU、DAU:MAU 和 WAU:MAU 比率以百分比形式计算用户参与度的粘性。

我有一个名为 my_table 的表,它需要

datetime_field user_id

此表列出了在给定datetime_field 上处于活动状态的所有user_id

对于前 6 个月(不包括当月),我想每天查看上述三个比率(DAU:WAU、DAU:MAU、WAU:MAU)。换句话说,对于每一天,我需要每日活跃用户(当天的用户数量)、过去一周的活跃用户(当天最后 7 天的用户数量)和活跃用户过去一个月(当天最后 30 天的用户数量不同)。

运行以下查询时(修改了变量名):

WITH s AS (
    SELECT
        DATE_TRUNC('day', datetime_field) AS dt,
        COUNT(DISTINCT user_id)::float AS dau
    FROM
        my_table
    WHERE
        datetime_field <= current_date - INTERVAL '1 month'
        AND datetime_field > current_date - INTERVAL '7 months'
    GROUP BY dt
)

SELECT
    dt,
    dau,
    (SELECT COUNT(DISTINCT user_id) FROM my_table WHERE datetime_field BETWEEN dt - 7 * INTERVAL '1 day' AND dt) AS wau,
    (SELECT COUNT(DISTINCT user_id) FROM my_table WHERE datetime_field BETWEEN dt - 30 * INTERVAL '1 day' AND dt) AS mau,
    dau / NULLIF(wau, 0) AS dau_wau,
    wau / NULLIF(mau, 0) AS wau_mau
FROM s
ORDER BY dt

我收到以下错误:

[Amazon](500310) Invalid operation: This type of correlated subquery pattern is not supported due to internal error;

当我仅使用 DAU:WAU 或仅使用 DAU:MAU 计算运行它时,它可以工作。但我还需要 WAU:MAU,因此我必须在一个查询中计算所有三个指标。有没有办法让它适用于所有指标?

【问题讨论】:

请提供示例数据、期望的结果以及您想要实现的逻辑的解释。 嗨@GordonLinoff,我已经在原帖中进一步阐述了我想要实现的目标。希望它能让事情更清楚! 【参考方案1】:

相关子查询的计算成本非常异常,Redshift 将对这些子查询的支持限制在优化器可以重写逻辑以并行高效处理的情况下。请参阅此 "Death by correlated subqueries" 博客文章,了解它们为何如此昂贵。

当 Redshift 给出“不支持相关子查询模式”消息时,您通常可以将查询重写为可以运行且速度更快的查询。以下重写在日历周/月上进行比较,而不是使用滚动日期窗口。

WITH data_set AS (
    SELECT DATE_TRUNC('day', datetime_field) AS dt
         , user_id                           
    FROM  my_table
    --May want to pin this range to calendar months
    WHERE datetime_field <= current_date - INTERVAL '1 month'
      AND datetime_field > current_date - INTERVAL '7 months'
    GROUP BY dt
), daily_count AS (
    SELECT dt
         , DATE_TRUNC('week', dt)   AS wk
         , DATE_TRUNC('month', dt)  AS mth
         , COUNT(DISTINCT user_id)  AS dau
    FROM  data_set
    GROUP BY dt
--Per calendar week (not rolling)
), weekly_count AS (
    SELECT DATE_TRUNC('week', dt)   AS wk
         , COUNT(DISTINCT user_id)  AS wau
    FROM  data_set
    GROUP BY wk
--Per calendar month (not rolling)
), monthly_count AS (
    SELECT DATE_TRUNC('month', dt)  AS mth
         , COUNT(DISTINCT user_id)  AS mau
    FROM  data_set
    GROUP BY mth
)
SELECT dt
     , dau
     , dau / NULLIF(wau, 0) AS dau_wau
     , wau / NULLIF(mau, 0) AS wau_mau
FROM daily_count
JOIN weekly_count  USING (wk)
JOIN monthly_count USING (mth)
ORDER BY dt

值得注意的是,这里的多个COUNT(DISTINCT x) 仍然相当昂贵。如果您打算频繁运行此分析和/或“切分”许多其他方面的不同计数,那么我建议使用Redshift's HyperLogLog functions,它可以让您以非常便宜的方式计算近似的不同计数。

【讨论】:

感谢乔,特别是您详尽的解释——这很有帮助!

以上是关于Redshift 中的 DAU WAU MAU 错误:[Amazon](500310) 无效操作:由于内部错误,不支持此类关联子查询模式;的主要内容,如果未能解决你的问题,请参考以下文章

使用 T-SQL 滚动 DAU、MAU

段的 DAU/MAU 计算

如何使用 BigQuery(参与度)计算 DAU/MAU

查询一段时间内的 DAU/MAU(每天)

LEFT OUTER JOIN 在 bigquery 上创建子查询时出错

产品经理日活跃用户「MAU」 和月活跃用户「DAU」