【问题标题】:ClickHouse Materialized View generating too slowClickHouse物化视图生成太慢
【发布时间】:2021-10-09 21:06:38
【问题描述】:

我们将原始事件收集到 ClickHouse 表中。表结构:

CREATE TABLE IF NOT EXISTS raw_events
(
    owner_id                  UInt32,
    user_id                   UInt32,
    event_datetime            DateTime,
    event_type_id             UInt8,
    unique_id                 FixedString(18),
    data                      String,
    attr_1                    UInt32,
    attr_2                    UInt32
)
    engine = MergeTree PARTITION BY toYYYYMMDD(event_datetime)
    ORDER BY (owner_id, user_id, event_type_id, event_datetime);

目前 raw_events 表包含 120000000 (120M) 行

我们的目标是向我们的用户展示这些事件的一些汇总统计数据,因此我们创建了一个物化视图:

CREATE MATERIALIZED VIEW test
ENGINE = AggregatingMergeTree() PARTITION BY (date)
ORDER BY (owner_id, user_id, date)
AS SELECT
       toYYYYMMDD(event_datetime) as date,
       owner_id,
       user_id,
       multiIf(
                   event_type_id == 1, 10,
                   event_type_id == 2, 20,
                   event_type_id == 3, 30,
                   event_type_id == 4, 40,
                   event_type_id == 32, 50,
                   event_type_id >= 64, 60,
                   0
           ) as status,
       attr_1,
       attr_2,
       COUNT() as count,
       COUNT(DISTINCT unique_id) as unique_count
   FROM raw_events
   GROUP BY owner_id, user_id, date, status, attr_1, attr_2
   ORDER BY owner_id, user_id, date;

如果我们单独运行选择查询,生成单个 owner_id 的响应大约需要 1 秒。但是为同一个选择创建一个物化视图需要太多时间。执行创建物化视图查询后,它只生成了 200 条记录,并且花费了 ~10 分钟。因此,为当前的 120M 记录表完全构建视图似乎需要几天时间。

我错过了什么?也许 order/group 子句有一些技巧可以让它运行得更快?目前,我只运行 select+group 查询而不是使用物化视图要容易得多。

附加问题:有没有办法检查现有表的物化视图构建进度?

【问题讨论】:

    标签: performance aggregate query-optimization clickhouse materialized-views


    【解决方案1】:
    1. AggregatingMergeTree -- 使用ORDER BY 作为折叠规则。
    2. AggregatingMergeTree -- 必须与 AggregateFunctions + -State + -Merge 组合器一起使用
    3. ORDER BY -- 过多
    CREATE MATERIALIZED VIEW test
    ENGINE = AggregatingMergeTree() PARTITION BY (date)
    ORDER BY (owner_id, user_id, date, status, attr_1, attr_2)         ---<<<<<<<<<<<<<<<<<<<<-----------
    AS SELECT
           toYYYYMMDD(event_datetime) as date,
           owner_id,
           user_id,
           multiIf(
                       event_type_id == 1, 10,
                       event_type_id == 2, 20,
                       event_type_id == 3, 30,
                       event_type_id == 4, 40,
                       event_type_id == 32, 50,
                       event_type_id >= 64, 60,
                       0
               ) as status,
           attr_1,
           attr_2,
           countState() as count,                                  ---<<<<<<<<<<<<<<<<<<<<-----------
           uniqState(unique_id) as unique_count        ---<<<<<<<<<<<<<<<<<<<<-----------
       FROM raw_events
       GROUP BY owner_id, user_id, date, status, attr_1, attr_2
    
    

    https://gist.github.com/den-crane/a72614fbe6d23eb9c2f1bce40c66893f

    https://gist.github.com/den-crane/49ce2ae3a688651b9c2dd85ee592cb15

    https://den-crane.github.io/Everything_you_should_know_about_materialized_views_commented.pdf

    【讨论】:

    • 完美,非常感谢!你提供的 pdf 文件有很多我以前找不到的有用信息。但我仍然对 unique_count 有疑问。它计算预期的行(组)中不同的 unique_id。但理想情况下,无论日期如何,我只需要计算一次唯一 ID。因此,如果我有所有参数的相同组合发生两次(在 29.01.2000 和 30.01.2000),我只想计算 29.01.2020 的唯一出现(按时间顺序排列的第一个)并在 2020 年 1 月 30 日忽略它。这甚至可能吗?还是您更愿意建议为此使用不同的方法?
    • 只是给你一些背景。同一事件在不同的日子发生两次。 “同一事件”是指所有者+用户+状态+attr1+attr2+uniqueid的独特组合。我们想显示用户的统计数据,以天为单位。在该统计数据上,我们希望仅在事件第一次发生时对其进行计数。但对我来说这看起来不可能,因为我们已经按天对所有内容进行了分组,并且聚合函数在这些组中使用。有什么建议?我被这个问题困扰了好几天了。
    • uniqState -- CH 存储状态(不是 uniq 的数量)。一切都将按照您对状态的预期工作。 clickhouse.tech/docs/en/sql-reference/aggregate-functions/… 试试一个简单的例子,两列十行。
    • 你好。现在几乎一切都在运行,再次感谢。唯一仍然无法正常工作的是 uniqs 的计数。我创建了 MV,它每小时对我的事件进行分组,并将 uniq 事件的状态保存为 uniqState(unique_id, status)。但是,如果同一事件发生两次(分别在 8 点和 9 点),则 uniqMerge() 会在 8 小时和 9 小时的行中显示“1”。我可以使用它,但理想情况下,我需要它在 MV 范围内计算 uniqs,以便它将返回“1”表示 8 小时行,“0”表示 9 小时行。这甚至可能吗?我觉得我可以通过聚合函数修饰符以某种方式实现它,但我没有看到任何解决方案
    • uniqState(unique_id, status) -- 这是不正确的。以create table / create MV / insert sample rows / query actual result / desired result 为例
    猜你喜欢
    • 2021-12-06
    • 2021-07-24
    • 2019-02-12
    • 2019-01-28
    • 2018-12-28
    • 2018-11-10
    • 2016-08-19
    • 2021-01-09
    • 2021-06-13
    相关资源
    最近更新 更多