级联物化视图
此示例演示如何创建一个物化视图,然后如何在第一个物化视图上级联第二个物化视图。在本页面中,您将看到如何进行操作、许多可能性以及限制。通过使用第二个物化视图作为源创建物化视图,可以解决不同的用例。
示例:
我们将使用一个虚构的数据集,展示一组域名每小时的浏览次数。
我们的目标
- 我们需要按月对每个域名的数据进行聚合,
- 我们还需要按年对每个域名的数据进行聚合。
您可以选择以下选项之一:
- 编写查询,在 SELECT 请求期间读取并聚合数据
- 在摄取时间将数据准备为一种新格式
- 在摄取时间将数据准备为特定的聚合。
使用物化视图准备数据将允许您限制 ClickHouse 需要处理的数据和计算量,使您的 SELECT 请求更快。
物化视图的源表
创建源表,因为我们的目标涉及对聚合数据的报告而非单个行,我们可以解析它,将信息传递给物化视图,并丢弃实际的输入数据。这满足了我们的目标并节省了存储,因此我们将使用 Null
表引擎。
您可以在 Null 表上创建物化视图。因此,写入表的数据最终将影响视图,但原始原始数据仍将被丢弃。
月度聚合表和物化视图
对于第一个物化视图,我们需要创建 Target
表,在这个示例中,它将是 analytics.monthly_aggregated_data
,我们将按月和域名存储浏览次数之和。
将数据转发到目标表的物化视图将如下所示:
年度聚合表和物化视图
现在我们将创建第二个物化视图,该视图将链接到之前的目标表 monthly_aggregated_data
。
首先,我们将创建一个新的目标表,该表将存储按年聚合的浏览次数之和。
此步骤定义了级联。 FROM
语句将使用 monthly_aggregated_data
表,这意味着数据流将是:
- 数据进入
hourly_data
表。 - ClickHouse 将转发接收到的数据到第一个物化视图
monthly_aggregated_data
表, - 最后,第2步接收到的数据将转发到
year_aggregated_data
。
在使用物化视图时,一个常见的误解是数据是从表中读取的。这不是 物化视图
的工作方式;转发的数据是插入块,而不是您表中的最终结果。
让我们想象在此示例中,monthly_aggregated_data
中使用的引擎是 CollapsingMergeTree,转发到我们第二个物化视图 year_aggregated_data_mv
的数据将不是已折叠表的最终结果,而是转发具有在 SELECT ... GROUP BY
中定义的字段数据块。
如果您使用 CollapsingMergeTree、ReplacingMergeTree,或者甚至是 SummingMergeTree,并且计划创建级联物化视图,您需要理解在此处描述的限制。
示例数据
现在是插入一些数据以测试我们的级联物化视图的时候了:
如果您 SELECT analytics.hourly_data
的内容,您会看到以下内容,因为表引擎是 Null
,但数据已被处理。
我们使用了一个小数据集,以确保我们可以跟踪和比较结果与我们的期望。一旦您的流与小数据集正确,您可以直接转到大量数据。
结果
如果您尝试通过选择 sumCountViews
字段查询目标表,您将看到二进制表示(在某些终端中),因为该值并不是以数字存储,而是作为 AggregateFunction 类型。
要获得聚合的最终结果,您应该使用 -Merge
后缀。
您可以使用以下查询查看存储在 AggregateFunction 中的特殊字符:
相反,让我们尝试使用 Merge
后缀来获取 sumCountViews
值:
在 AggregatingMergeTree
中,我们将 AggregateFunction
定义为 sum
,因此我们可以使用 sumMerge
。当我们在 AggregateFunction
上使用 avg
函数时,我们将使用 avgMerge
,依此类推。
现在我们可以审核物化视图是否满足我们定义的目标。
现在我们已经在目标表 monthly_aggregated_data
中存储了数据,我们可以获取按月对每个域名聚合的数据:
按年聚合每个域名的数据:
将多个源表合并到单个目标表
物化视图还可以用于将多个源表合并到同一个目标表中。这对于创建一个类似于 UNION ALL
逻辑的物化视图非常有用。
首先,创建两个源表,表示不同集合的指标:
然后使用合并后的指标集创建 Target
表:
创建两个指向相同 Target
表的物化视图。您不需要显式包含缺失的列:
现在,当您插入值时,这些值将根据其各自的列聚合到 Target
表中:
Target
表中组合的浏览次数和点击次数:
此查询应输出如下内容: