跳转到主要内容
用户常问的一个问题是:什么时候该使用 materialized views,什么时候该使用 投影。本文将探讨两者之间的关键区别,以及在某些场景下 为什么你可能会选择其中一种而不是另一种。

关键差异总结

下表总结了 materialized view 与投影在各个考量方面的关键差异。

比较 materialized views 与 投影

何时选择 materialized views

在以下情况下,你应考虑使用 materialized views:
  • 处理 实时 ETL 和多阶段数据管道 时:你需要在数据到达时执行复杂的转换、聚合,或对数据进行路由,并且可能需要通过串联视图跨多个阶段处理。
  • 你需要 复杂的反规范化:你需要将来自多个来源 (表、子查询或字典) 的数据预先 JOIN 到一张针对查询优化的单一表中,尤其是在可以接受使用可刷新materialized view定期执行全量刷新的情况下。
  • 你希望 显式控制 schema:你需要为预计算结果使用一张独立且明确的目标表,并拥有其自身的 schema 和 engine,从而为数据建模提供更大的灵活性。
  • 你希望在 摄取时进行过滤:你需要在数据被 materialized 之前 进行过滤,从而减少写入目标表的数据量。

何时应避免使用 materialized views

在以下情况下,应考虑避免使用 materialized views:
  • 源数据经常更新或删除:如果没有额外策略来处理源表与目标表之间的一致性,增量materialized view 可能会变得陈旧,从而导致数据不一致。
  • 更看重简洁性和自动优化:如果你希望避免管理单独的目标表。

何时选择 投影

在以下情况下,你应考虑使用 投影:
  • 优化单个表的查询:你的主要目标是通过提供替代排序顺序、优化主键之外列上的过滤条件,或为单个表预先计算聚合,来加速单个基表上的查询。
  • 你希望具备查询透明性:也就是说,你希望查询无需修改即可直接针对原始表执行,并依赖 ClickHouse 为给定查询选择最佳的数据布局。

何时应避免使用投影

在以下情况下,应考虑避免使用投影:
  • 需要复杂的数据转换或多阶段 ETL:投影定义不支持 JOIN 操作,无法串联形成多步骤管道,也无法处理某些 SQL 功能,例如窗口函数或复杂的 CASE 语句。虽然对包含投影的表进行查询时可以自由使用 join,但投影本身并不适合复杂的数据转换。
  • 需要对 materialized 数据进行显式过滤:投影定义中不支持 WHERE 子句,因此无法过滤将被 materialized 到投影中的数据。
  • 使用非 MergeTree 表引擎:投影仅适用于使用 MergeTree 引擎家族的表。
  • FINAL 查询必不可少:投影无法与 FINAL 查询配合使用,而后者有时会用于去重。
  • 如果需要并行副本,也应避免使用投影,因为投影不支持该功能。

总结

materialized views 和 投影 都是优化查询和转换数据的强大工具。通常,我们不建议把它们视为非此即彼的选择。相反,两者可以互为补充,结合使用,以充分发挥查询性能。因此,在 ClickHouse 中选择 materialized views 还是 投影,实际上取决于你的具体使用场景和访问模式。 一般来说,如果你需要将一个或多个源表中的数据聚合到目标表,或者在大规模场景下执行复杂转换,就应考虑使用 materialized views。materialized views 非常适合将高成本聚合的工作从查询时前移到写入时。对于按日或按月的 rollup、实时仪表盘或数据汇总,它们都是很好的选择。 另一方面,如果你需要优化那些按与表主键不同的列进行过滤的查询,则应使用 投影。主键决定了数据在磁盘上的物理排序。尤其是在无法再更改表主键,或者你的访问模式比主键所能覆盖的场景更多样时,投影 会特别有用。
最后修改于 2026年6月10日