You need to enable JavaScript to run this app.
文档中心
ByteHouse云数仓版

ByteHouse云数仓版

复制全文
下载 pdf
物化视图
物化视图概述
复制全文
下载 pdf
物化视图概述

物化视图(Materialized View)​通过预计算和存储查询结果,配合自动查询改写(Query Rewrite),物化视图可在不修改原始 SQL 的情况下提升查询性能,尤其适用于需要加速高频报表、仪表盘查询或复杂多表关联分析的场景。
但是物化视图通过预计算来实现性能优化就意味着其具有一定的存储和数据维护性成本,建议先完成数据类型选择、主键设计等基础优化,再针对需要进一步加速的查询模式使用物化视图。
本文将为您介绍物化视图的概念、两种类型(同步与异步)的原理、使用场景及差异对比。

基本概念

  • 基表(Base Table)- 也叫源表(原始表),物化视图的驱动表,异步物化视图支持 JOIN 和子查询等多表查询方式。
  • 目标表(Target Table)- 物化视图实际存储的表,一般是 AggregateMergeTree 或者 MergeTree。
  • 物化视图(Materialized View)- 逻辑概念,定义基表到目标表的映射关系。
  • 刷新(Refresh)- 是指重新计算并更新物化结果,使其反映基表变化的过程。同步物化视图在基表写入时触发计算;异步物化视图通过定时调度或手动操作触发刷新。
  • 查询改写(Query Rewrite)- 查询改写是指在对已构建了物化视图的基表进行查询时,系统自动判断是否可以复用物化视图中的预计算结果处理查询。如果可以复用,系统会直接从相关的物化视图读取预计算结果,以避免重复计算消耗系统资源和时间。

同步物化视图(Synchronous Materialized View)

基本介绍

特点:

  • 数据实时性高:基表数据变更时,物化视图立即更新。
  • 强一致性:基于同一个事务更新基表和物化视图的数据,具有相同的可见性。
  • 写入延迟:可能会增加基表的写入延迟。

优势:

  • 数据始终保持最新状态,适用于对实时性要求极高的场景。
  • 查询时可以保证获取到最新数据。
  • 适合数据量相对较小,更新频率不是特别高的场景。

缺点:

  • 推荐适用于单表预聚合场景,多表场景下可能存在一致性问题。
  • 会增加基表写入链路的处理开销,具体影响请参见使用限制与注意事项。

原理简介

ByteHouse 的同步物化视图设计继承自 ClickHouse 社区版的增量物化视图机制,针对云原生架构进行了适配和增强。

注意

ClickHouse 社区版中**“增量物化视图”​的语义,主要是指每次仅将本次写入基表的增量数据写入物化视图目标表;与 ByteHouse 基于增量计算(Dynamic Table)​**技术实现的增量物化视图和增量视图维护(IVM, Incremental View Maintenance)并不是同一概念。

同步物化视图的基本原理,是在数据写入阶段预先完成聚合、过滤或转换,并将计算结果写入目标表。与原始数据相比,物化后的数据通常规模更小。例如在聚合场景中,目标表只需保存部分聚合结果或草图数据。查询时可以直接基于这些预计算结果进行分析,无需重复扫描原始数据并执行复杂计算,因此查询语句更简单,执行效率也通常更高。
与 Postgres 这类事务型数据库不同,ByteHouse 中的同步物化视图本质上类似一个触发器:当数据块被插入到基表时,它会在这些新插入的数据块上执行一条查询,并物化查询结果。即当基表发生数据写入时,系统会自动触发物化视图定义中的查询逻辑,并将查询结果写入对应的目标表。如果后续又有更多数据写入,物化视图会再次针对新插入的数据块执行查询,并把结果继续写入目标表。目标表中的中间结果会不断被更新和合并。
在单表追加写入,并且聚合逻辑与目标表引擎配置正确的情况下,查询时合并目标表中的中间结果,可以得到与在全部原始数据上执行相应聚合一致的结果。多表 JOIN 和唯一键表等场景存在额外限制,具体请参见下文的“使用限制与注意事项”。

使用限制与注意事项

  1. 提高基表写入的成本: 同步物化视图会在基表写入过程中额外触发一次目标表写入。因此,相比直接写入基表,开启同步物化视图后会增加写入链路的处理开销。因此,在高写入吞吐场景下,同步物化视图可能带来以下影响:增加基表写入延迟;降低整体写入吞吐;增加目标表路由、写入和存储压力。
    • 对写入延迟不敏感、查询收益明确的场景,同步物化视图可以显著降低查询成本。
    • 对于写入吞吐敏感或计算逻辑较重的场景,则需要谨慎使用。
  2. JOIN 场景的限制: ClickHouse 的同步物化视图类似“写入触发器”。当基表发生数据写入时,仅针对本次新增的数据块执行物化视图定义的 SQL,并将计算结果写入目标表。因此在多表 JOIN 场景中,同步物化视图通常只由其中一张基表的写入动作触发,仅使用触发写入瞬间各关联表“当前可见”的数据进行计算,因此从设计上就无法避免一致性风险。
    Image

如上图所示,关联表后续的新增、更新或删除不会更新物化视图中已物化的历史结果,因此其结果可能与直接查询基表的结果不一致。这类场景要求关联维表保持不变;若维表发生变化,则需手动重算并更新受影响的历史结果,以恢复一致性。

  1. 不支持唯一键表:

同步物化视图按每次新写入的数据块执行计算,不会自动继承基表的 Unique Key 去重和更新语义。因此当基表因去重或更新淘汰旧记录时,已经写入物化视图目标表的旧记录或聚合贡献不会随之自动撤回,因此可能与去重后的基表查询结果不一致;目标表自身的合并也不保证消除这类差异。

异步物化视图(Asynchronous Materialized View)

异步物化视图通过定时调度或手动触发全表或者分区级别的预计算并存储查询结果,减少重复扫描、关联和聚合。配合透明查询改写,可在不修改原始 SQL 的情况下加速查询。

使用要点

使用异步物化视图前,建议先确认以下要点:

  • 是否有可复用的计算? 高频聚合、多表 JOIN 等重复计算较多的查询,通常更容易获得收益。
  • 基表是否适合异步刷新? 优先考虑批量更新的事实表和相对稳定的维表;频繁变更可能带来较高刷新成本。
  • 能否按分区刷新? 合理对齐基表与物化视图的分区,可将表级刷新优化为分区级刷新,从而减少刷新时的扫描和计算。
  • 用于数据加工还是查询加速? 加工场景通常直接查询物化结果,需关注刷新进度和数据延迟;加速场景通过透明改写复用物化结果,在满足一致性检查和补偿条件时,结合基表返回完整且一致的结果。
  • 收益能否覆盖成本? 综合评估减少的重复计算或查询开销,以及新增的存储和刷新成本。
  • 计算资源是否充足? 为刷新配置合适的计算组,确保资源能够支撑刷新负载;资源不足可能导致刷新延迟或失败。

常见的使用场景如下:

场景

说明

重复聚合查询

预先汇总销售额、访问量等常用指标,加速报表和看板查询

多表关联查询

预计算关联与聚合结果,减少查询时执行复杂 JOIN 的开销,适合事实表批量更新、维表相对稳定的场景

原理简介

异步物化视图将计算过程与基表写入解耦,通过定时调度或手动触发更新物化结果。刷新流程主要包括确定刷新范围、调度执行任务、更新版本信息三个步骤。

  1. 确定刷新范围

刷新触发后,系统检测基表变化,并根据基表与物化视图之间的分区映射确定需要重新计算的范围:

  • 能够建立分区映射:根据发生变化的基表分区,定位受影响的目标分区,仅重算这些分区,使用分区级刷新。
  • 无法建立分区映射:无法将变化范围限定到具体目标分区,需要重新计算整张物化视图,使用整表级别刷新。

需要注意,分区映射缩小的是刷新范围;被选中的分区仍需完整重算,并非只处理新增记录。

  1. 调度并执行刷新任务

确定刷新范围后,系统会组织并下发调度任务:

  • 分区级刷新:将受影响的目标分区拆分为分区刷新任务,按照配置的并发度并行执行;超过并发上限的任务等待后续调度。
  • 表级刷新:生成一个全表刷新任务,重新计算整张物化视图。

每个任务执行物化视图定义的查询,读取对应范围内的基表数据,并通过 INSERT OVERWRITE 等机制覆盖原有物化结果。合理设置并发度,有助于兼顾刷新效率与资源占用,减少对同一计算组中其他业务查询的影响。

  1. 更新刷新版本信息

刷新成功后,系统会记录本次物化结果对应的基表版本,用于后续变化检测和查询改写的一致性检查。在 ByteHouse 云数仓版中,目标数据覆盖与刷新元数据更新在同一事务中提交,保持物化结果与版本记录一致。
若基表随后再次变化,系统会在后续检查中重新识别受影响的目标分区,并安排刷新。

分区刷新示例

假设使用异步物化视图对销售表按天、按商品预聚合,统计销售额。
基表和目标表均按销售日期分区,建立“基表某一天的分区 → 目标表同一天的分区”的映射,刷新行为如下:

基表变化

分区映射与定位

刷新行为

1 月 1 日新增一批订单

基表 1 月 1 日分区 → 目标表 1 月 1 日分区

重算当天分区内的全部订单数据,覆盖当天的汇总结果

1 月 2 日修正部分订单金额

基表 1 月 2 日分区 → 目标表 1 月 2 日分区

重算当天分区内的全部订单数据,覆盖当天的汇总结果

1 月 3 日没有变化

对应目标分区不受影响

保留已有结果,无需重算

JOIN 场景为何可能扩大刷新范围

当异步物化视图包含 JOIN(多表关联)时,系统需要分别判断各张基表的变化会影响哪些目标分区。
对于按日期分区的订单事实表,订单数据本身包含订单日期。因此,当某一天的订单发生变化时,系统可以通过日期分区映射,直接定位并刷新对应日期的目标分区。
但商品、用户等维表通常按业务实体组织,其中的数据一般不包含订单日期。一条维表记录可能与多个日期分区中的事实数据关联。因此,维表发生变化时,系统可能无法仅根据这条变更记录,直接判断哪些日期分区受到了影响。
例如,订单事实表按订单日期分区,商品维表记录商品 ID 和商品分类。物化视图将两张表关联,并按日期和商品分类汇总销售额:

数据变化

系统能否直接定位日期分区

刷新范围

1 月 2 日新增订单

可以。订单记录中包含订单日期

仅刷新 1 月 2 日对应的目标分区

商品 A 的分类由“数码配件”改为“智能设备”

不可以。商品记录本身不能说明商品 A 曾在哪些日期产生订单

需要扩大刷新范围,按照全部目标分区进行刷新

假设商品 A 在 1 月 1 日和 1 月 2 日都有订单,从业务结果看,这两个日期的分类汇总都会受到影响。但系统仅根据商品维表的变更记录,无法直接确定商品 A 关联了哪些日期分区。为保证刷新后的结果完整、正确,需要将全部目标分区标记为待刷新。
因此,即使事实表与目标表之间已经建立了日期分区映射,维表变化仍可能触发范围更大的刷新。包含多表 JOIN 的异步物化视图更适合维表相对稳定的场景;如果维表频繁变化,刷新成本可能明显增加。

刷新成本

异步物化视图的刷新成本很大程度上取决于能否建立基表分区到物化视图目标分区的映射关系,这里分为两种情况讨论:

  • 分区级刷新:能够建立分区映射,根据基表变化定位并重算受影响的目标分区。
    • 成本主要取决于受影响的分区数量、分区内的数据量,以及查询的计算复杂度。
  • 表级刷新:无法建立分区映射,不能将变化范围限定到具体分区,需要重新计算整张物化视图。
    • 成本主要取决于视图定义涉及的基表数据总量,以及查询的计算复杂度。

在多表 JOIN 场景中,即使事实表分区已对齐,关联维表的变化仍可能影响全部目标分区。因此,异步物化视图更适合事实表批量更新、维表相对稳定的场景。
合理设计分区映射、设置刷新范围并配置合理的计算资源,有助于控制刷新成本和数据延迟。

两种物化视图的对比

对比项

同步物化视图

异步物化视图

数据一致性

和基表相同事务写入,与基表强一致

异步刷新,提供最终一致性,数据存在一定延迟

历史数据处理

创建视图前的历史数据,需按业务需求手动回填

通过刷新机制自动处理刷新范围内的历史数据

多表关联

受限支持;关联表变化不会自动更新已物化的历史结果

支持;维表变化可能触发全部目标分区刷新

数据时效

基表写入时同步计算,但会增加写入开销

以最近一次成功刷新结果为准,存在刷新延迟

查询改写

支持

支持

计算开销

计算发生在数据写入过程中,可能增加写入延迟、降低导入吞吐量

刷新单独消耗计算资源;建议使用独立计算组,也可根据负载情况复用现有计算组

总的来说,同步视图和异步视图各有其优势和适用场景。选择哪种类型的物化视图,需要根据具体的业务需求、数据特征和系统资源情况来权衡。在实际应用中,可能会同时使用这两种类型的视图来满足不同的需求。

最近更新时间:2026.10.15 21:32:29
这个页面对您有帮助吗?
有用
有用
无用
无用