跳至主要内容

可刷新物化视图(实验性功能)

实验性功能。 了解更多。

可刷新物化视图在概念上类似于传统 OLTP 数据库中的物化视图,它存储指定查询的结果以便快速检索,并减少重复执行资源密集型查询的需要。与 ClickHouse 的 增量物化视图 不同,此功能需要定期对完整数据集执行查询,并将结果存储在目标表中以供查询。理论上,此结果集应该小于原始数据集,从而使后续查询能够更快地执行。

Refreshable materialized view diagram

何时应该使用可刷新物化视图?

ClickHouse 增量物化视图功能强大,并且通常比可刷新物化视图使用的方法具有更好的扩展性,尤其是在需要对单个表进行聚合的情况下。通过仅在插入每个数据块时计算聚合,并在最终表中合并增量状态,查询仅在数据子集上执行。此方法可以扩展到可能数 PB 的数据,并且通常是首选方法。

但是,在某些情况下,不需要或不适用此增量过程。某些问题要么与增量方法不兼容,要么不需要实时更新,定期重建更合适。例如,您可能希望定期对完整数据集上的视图进行完整重新计算,因为它使用了复杂的联接,这与增量方法不兼容。

可刷新物化视图可用于运行批量处理过程,执行诸如反规范化之类的任务。可以在可刷新物化视图之间创建依赖关系,以便一个视图依赖于另一个视图的结果,并且仅在其完成后执行。这可以用于替换计划好的工作流或简单的 DAG,例如 dbt 作业。

示例

例如,考虑以下查询,将 postlinks 数据集反规范化到 StackOverflow 数据集的 posts 表中。我们在 数据建模/反规范化 指南中探讨了用户可能希望执行此操作的原因。

SELECT
posts.*,
arrayMap(p -> (p.1, p.2), arrayFilter(p -> p.3 = 'Linked' AND p.2 != 0, Related)) AS LinkedPosts,
arrayMap(p -> (p.1, p.2), arrayFilter(p -> p.3 = 'Duplicate' AND p.2 != 0, Related)) AS DuplicatePosts
FROM posts
LEFT JOIN (
SELECT
PostId,
groupArray((CreationDate, RelatedPostId, LinkTypeId)) AS Related
FROM postlinks
GROUP BY PostId
) AS postlinks ON posts_types_codecs_ordered.Id = postlinks.PostId

postspostlinks 表都可能被更新。与其尝试使用增量物化视图实现此联接,不如简单地计划此查询以设定间隔(例如,每小时一次)运行,并将结果存储在 post_with_links 表中。

我们的语法与增量物化视图相同,除了我们包含一个 REFRESH 子句

--enable experimental feature
SET allow_experimental_refreshable_materialized_view = 1

CREATE MATERIALIZED VIEW posts_with_links_mv
REFRESH EVERY 1 HOUR TO posts_with_links AS
SELECT
posts.*,
arrayMap(p -> (p.1, p.2), arrayFilter(p -> p.3 = 'Linked' AND p.2 != 0, Related)) AS LinkedPosts,
arrayMap(p -> (p.1, p.2), arrayFilter(p -> p.3 = 'Duplicate' AND p.2 != 0, Related)) AS DuplicatePosts
FROM posts
LEFT JOIN (
SELECT
PostId,
groupArray((CreationDate, RelatedPostId, LinkTypeId)) AS Related
FROM postlinks
GROUP BY PostId
) AS postlinks ON posts_types_codecs_ordered.Id = postlinks.PostId

该视图将立即执行,并根据配置每小时执行一次,以确保源表中的更新反映出来。重要的是,当查询重新运行时,结果集将以原子方式和透明方式更新。