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

您还可以观看以下视频:
何时应使用可刷新的物化视图?
ClickHouse 的增量物化视图功能强大,通常比可刷新的物化视图所使用的方法具有更好的扩展性,尤其是在需要对单一表执行聚合的情况下。通过仅计算按块插入的数据的聚合,并在最终表中合并增量状态,查询只会在部分数据上执行。这种方法可以扩展到潜在的 PB 级数据,通常是首选的方法。
但是,有些情况下不需要或不适用这种增量过程。一些问题与增量方法不兼容,或不需要实时更新,而周期性重建更为合适。例如,您可能希望定期对完整数据集重新计算视图,因为它使用了复杂的连接,这在增量方法中是不可兼容的。
可刷新的物化视图可以运行批处理过程,执行诸如去规范化的任务。可以在可刷新的物化视图之间创建依赖关系,以便一个视图依赖于另一个视图的结果,并只有在完成后才会执行。这可以替代计划工作流或简单的 DAG,如 dbt 作业。要了解有关如何设置可刷新的物化视图之间的依赖关系,请访问 CREATE VIEW 的
Dependencies
部分。
如何刷新可刷新的物化视图?
可刷新的物化视图将在创建时定义的间隔内自动刷新。 例如,以下物化视图每分钟刷新一次:
如果您想强制刷新物化视图,可以使用 SYSTEM REFRESH VIEW
子句:
您还可以取消、停止或启动视图。 有关更多详细信息,请参见 管理可刷新的物化视图 文档。
可刷新的物化视图上次刷新是何时?
要找出可刷新的物化视图上次被刷新时,可以查询 system.view_refreshes
系统表,示例如下:
如何更改刷新频率?
要更改可刷新的物化视图的刷新频率,请使用 ALTER TABLE...MODIFY REFRESH
语法。
完成后,您可以使用 可刷新的物化视图上次刷新是何时? 查询来检查频率是否已更新:
使用 APPEND
添加新行
APPEND
功能允许您将新行添加到表的末尾,而不是替换整个视图。
此功能的一个用法是捕获某个时刻值的快照。例如,假设我们有一个从 Kafka 、 Redpanda 或其他流数据平台传入消息流填充的 events
表。
此数据集在 uuid
列中有 4096
个值。我们可以编写以下查询来找到总计数最高的值:
假设我们想要每 10 秒捕获一次每个 uuid
的计数,并将其存储在名为 events_snapshot
的新表中。 events_snapshot
的模式将如下所示:
然后我们可以创建一个可刷新的物化视图来填充此表:
然后我们可以查询 events_snapshot
,以获取特定 uuid
随时间变化的计数:
示例
现在让我们看看如何使用可刷新的物化视图与一些示例数据集。
Stack Overflow
去规范化数据指南展示了使用 Stack Overflow 数据集去规范化数据的各种技术。我们将数据填充到以下表中:votes
、users
、badges
、posts
和 postlinks
。
在该指南中,我们展示了如何通过以下查询将 postlinks
数据集去规范化为 posts
表:
随后我们展示了如何一次性将该数据插入到 posts_with_links
表中,但在生产系统中,我们希望定期运行此操作。
posts
和 postlinks
表都有可能被更新。因此,与其尝试使用增量物化视图实施此连接,可能仅需安排此查询在设定的时间间隔内运行,例如每小时一次,将结果存储在 post_with_links
表中。
在这种情况下,可刷新的物化视图将大有裨益,我们可以通过以下查询创建一个:
该视图将立即执行,并在此后每小时根据配置确保源表的更新反映。重要的是,当查询重新运行时,结果集将原子性和透明地更新。
这里的语法与增量物化视图相同,只是我们加入了 REFRESH
子句:
IMDb
在 dbt 和 ClickHouse 集成指南 中,我们使用以下表填充了一个 IMDb 数据集:actors
、directors
、genres
、movie_directors
、movies
和 roles
。
然后我们可以编写以下查询,以计算每位演员的总结,按电影出演最多的人进行排序。
虽然返回结果并不需要太长时间,但假设我们希望让它更快,并且计算开销更小。 假设该数据集也会不断更新——新电影持续上线,新的演员和导演也在出现。
这时候就该使用可刷新的物化视图了,所以我们首先为结果创建一个目标表:
现在我们可以定义视图:
该视图将立即执行,并在此后每分钟根据配置确保源表的更新反映。我们的原查询就变得语法上更简单,速度显著更快!
假设我们向源数据添加了一个新演员“Clicky McClickHouse”,他在很多电影中都出现过!
不到 60 秒后,我们的目标表更新以反映 Clicky 演出的丰硕成果: