Apache Doris 异步物化视图与 Snowflake MV / Dynamic Tables 工程化对照

摘要

在面向分析的数据分层建模里,物化视图是降低重复计算、缩短查询响应时间的通用手段。Apache Doris 的异步物化视图从 2.1 版本引入、3.0 版本完善,以一套机制覆盖了多表 join、嵌套分层、分区增量刷新与构建资源管控;Snowflake 则把单表加速与多表管道拆成两套独立机制------Materialized Views 与 Dynamic Tables,前者有严格的单表与聚合限制,后者以 TARGET_LAG 声明数据新鲜度。官方口径下,Doris 在 TPC-H 100G 单节点测试中透明改写相比普通查询响应时间降低约 99%,湖仓外表场景查询提速约 93 倍。本篇把两边的能力边界、成本结构与接入语法逐条对齐,供数据分层建模时选对工具,不做简单的优劣定性。

一、先说结论

  • Apache Doris 异步物化视图 :Doris 将物化视图做成异步、可声明刷新策略的能力,构建与查询得以解耦,这是它与 Snowflake MV 自动维护思路的根本分歧。该能力 2.1 版本引入、3.0 版本完善,支持多表 join、嵌套物化视图、全量与分区增量刷新,以及基于 SPJG 模式的透明改写(2.1.5 起默认开启),并可用 workload_group 限制构建与刷新的资源占用。官方口径下,TPC-H 100G 单节点测试中透明改写相比普通查询响应时间降低约 99%,湖仓外表场景查询提速约 93 倍。分区增量刷新指仅刷新基表发生变化的那些分区,而非每次全量重算,对大分区表的成本影响最直接。
  • Snowflake Materialized Views :需 Enterprise Edition 起,官方明确限制为单表(不支持 join)、聚合函数受限(不支持窗口函数、不支持 COUNT DISTINCT)、不支持嵌套子查询,由系统自动维护并消耗专属的 MATERIALIZED_VIEW_MAINTENANCE 仓库 credits,该 credits 不受 Resource Monitor 管控。这些限制决定了 Snowflake MV 更适合"单表预聚合"这一类窄场景,复杂管道需另一套机制兜底。
  • Snowflake Dynamic Tables :2024-04-29 GA,官方建议将其作为新建多表 SQL 管道的首选;以 TARGET_LAG 声明数据新鲜度,刷新分 incremental 与 full 两种,官方明确不会因变更量大而自动降级为全量刷新。TARGET_LAG 把"数据要新到什么程度"变成一个可声明的参数,是 Dynamic Tables 相比 MV 在工程化上的主要不同。
  • 选型落点:单表聚合加速两边都能做;多表管道、嵌套分层、分区增量与刷新资源管控这几项,是差异集中区,也是技术选型时要逐条核对的清单。

二、问题怎么产生

物化视图解决的是"重复计算"问题:把昂贵的计算提前算好并存储,查询到来时直接取结果,而不是每次都重跑。其价值在于预计算并存储结果集,查询到达即取用,免掉重复执行。但"建了就快"是一种误解:它有两个容易被低估的代价------维护成本(刷新要消耗计算资源)与能力边界(哪些 SQL 能被物化)。这两件事直接决定一个物化视图"能不能用、用得起"。

Snowflake 的处理方式是将单表加速与多表管道拆成两套独立机制:单表场景用 Materialized Views,多表管道用 Dynamic Tables。Doris 则以一套异步物化视图覆盖从单表聚合到多表分层建模的多数场景。机制划分的不同,会带来接入方式、成本结构与限制清单的差异,下文逐层展开。

还有一个常被忽略的点:物化视图的维护本身会消耗资源,且消耗的是独立的算力账单。如果维护成本压过了查询收益,物化视图反而变成负担。因此比较两套机制,不能只看"能不能加速",还要看"维护起来贵不贵、能不能限"。

三、怎么做

下面按"建视图、开改写、看监控"与"Snowflake 两套写法"两个角度,把接入差异落到具体语法上,并补充参数表与验证步骤,便于工程落地直接复用。

3.1 Doris:多表聚合 + 分区增量 + 资源管控

一个覆盖多表 join 的物化视图,可以同时指定分区增量刷新与构建资源组:

SQL 复制代码
CREATE MATERIALIZED VIEW region_revenue_mv
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
PROPERTIES (
  "replication_num" = "1",
  "workload_group" = "mv_build_group"
)
AS
SELECT
    n_name, r_name,
    date_trunc(o_orderdate, 'month') as month,
    bitmap_union(to_bitmap(o_orderkey)) as order_count,
    sum(l_extendedprice * (1 - l_discount)) as net_revenue
FROM orders o
JOIN lineitem l ON o.o_orderkey = l.l_orderkey
JOIN customer c ON o.o_custkey = c.c_custkey
JOIN nation n ON c.c_nationkey = n.n_nationkey
JOIN region r ON n.n_regionkey = r.r_regionkey
GROUP BY n_name, r_name, month;

workload_group 这一行是关键:它把物化视图的构建与正常查询隔开,避免大视图刷新把在线查询的算力挤掉。分区增量刷新则让每天只变动的分区被重算,其余分区原样保留,而不是整表推倒重来。

3.2 透明改写与监控

透明改写默认开启,原始查询无需改动即可被优化器改写为命中该视图:

SQL 复制代码
-- Doris 2.1.5 起透明改写默认开启;如需显式开启:
SET enable_materialized_view_rewrite = true;

-- 查看物化视图刷新任务状态与资源消耗
SELECT * FROM tasks("type"="mv")
WHERE MvName = 'region_revenue_mv'
ORDER BY CreateTime DESC;

3.3 关键参数配置表

下面把接入与调优中涉及的主要参数、建议值与适用场景汇总,便于一次性对照:

参数名 建议值 作用 适用场景
workload_group mv_build_group 将物化视图构建与正常查询隔开,限制刷新资源占用 Doris 异步 MV 建表 PROPERTIES,避免大视图刷新挤占在线算力
enable_materialized_view_rewrite true 开启透明改写,原始查询无需改动即可命中视图 Doris 2.1.5 起默认开启,可显式设置
replication_num 1 设置物化视图副本数,单节点或资源受限环境常用 构建环境按可用节点数调整
TARGET_LAG '10 minutes' 声明 Dynamic Table 数据新鲜度,刷新按此延迟目标调度 Snowflake Dynamic Table 多表管道
REFRESH AUTO ON MANUAL ON MANUAL 定义异步物化视图的刷新触发方式 Doris 异步 MV 建表语句
materialized_view_rewrite_enable_contain_external_table 开启 允许外表参与透明改写,需接受一致性窗口或自行保证外表一致 Doris 外表物化视图场景

3.4 验证步骤

落地后建议按以下顺序验证:先确认物化视图构建成功(查看 tasks("type"="mv") 状态或相应元信息);再执行一条本应命中视图的原始查询,结合执行计划确认发生了透明改写;最后观察 tasks("type"="mv") 中的资源消耗,确认 workload_group 已生效隔离。上述 tasks("type"="mv") 查询即是最直接的刷新与资源监控入口,可配合 mv_infos 一起核对视图状态。

3.5 Snowflake:单表 MV 与多表 DT 两套写法

Snowflake 的 Materialized View 仅支持单表、不支持 join,多表逻辑需先落到单表再物化;多表管道则用 Dynamic Table:

SQL 复制代码
-- Snowflake Materialized View:仅支持单表、不支持 join
CREATE MATERIALIZED VIEW region_daily_mv
AS SELECT r_name, sum(l_extendedprice) AS revenue
FROM region_sales_agg          -- 需先聚合到单表
GROUP BY r_name;

-- Snowflake Dynamic Table:多表管道推荐,TARGET_LAG 控制新鲜度
CREATE DYNAMIC TABLE region_pipeline_dt
  TARGET_LAG = '10 minutes'
  WAREHOUSE = my_wh
AS
SELECT n_name, sum(l_extendedprice) AS revenue
FROM orders o JOIN lineitem l ON o.o_orderkey = l.l_orderkey
GROUP BY n_name;

上方 MV 示例里 join 被刻意省略------Snowflake MV 不允许 join,多表逻辑必须先落到单表;Dynamic Table 才承接多表管道,且用 WAREHOUSE 显式绑定刷新算力。

从接入上看,Doris 一侧用一条 CREATE MATERIALIZED VIEW 即可表达多表管道,Snowflake 一侧要按场景在 MV 与 DT 之间选型,且 MV 的 SQL 写法受单表约束。实际项目里,若已有单表聚合层,Snowflake 侧将其物化成 MV,再往上叠多表汇总交给 DT,两层之间靠 TARGET_LAG 串起新鲜度;Doris 侧则可在同一异步 MV 体系内完成分层,少一套机制要学。

四、维度对照表

下面这张表把八项关键事实并排列出。重点看"多表 join""嵌套""刷新资源管控""查询重写开关"这四行------它们决定了复杂分层建模里谁更省事。

维度 Apache Doris 异步物化视图 Snowflake(MV / Dynamic Tables)
Edition 门槛 开源免费 MV 需 Enterprise Edition;DT 无单独 Edition 门槛(按仓库计费)
多表 join 支持 MV 不支持(单表);DT 支持(INNER/CROSS 全支持,OUTER 仅等值,LATERAL 不支持)
嵌套 支持嵌套物化视图改写 MV 不支持嵌套子查询;DT 支持基于另一 DT 构建
聚合能力 支持 GROUPING SETS / ROLLUP / CUBE、COUNT DISTINCT(bitmap 类) MV 不支持窗口函数、不支持 COUNT DISTINCT;DT 支持 GROUP BY(ROLLUP/CUBE/GROUPING SETS 不支持)、窗口函数有例外
刷新机制 全量 / 分区增量(仅刷变化分区) MV 自动维护(serverless);DT incremental / full(不自动降级全量)
刷新资源管控 workload_group 限制构建资源 MV 维护 credits 不受 Resource Monitor 管控;DT 可挂 Resource Monitor 到分配仓库
查询重写 透明改写默认开(SPJG 算法) 优化器自动重写,无明确开关;基表有 clustering 时可能扫基表
刷新监控 tasks("type"="mv") / mv_infos DYNAMIC_TABLE_REFRESH_HISTORY
国产化适配 / 信创 Doris 已完成鲲鹏/海光/飞腾等国产 CPU 与麒麟/统信 UOS/openEuler 适配,通过等保三级、可信数据库认证,满足政务/金融/央国企国产化替代 中国区由 AWS cn-northwest-1(宁夏)承载、神州数码云运营,使用独立域名且与全球区账户隔离,未纳入信创目录
商业化服务 / 企业级部署 开源自行部署;商业化由 SelectDB 提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源版 100% 兼容 Snowflake, Inc.(美国)提供仅托管云,无私有化部署选项

上面这些约束,本质都是"能力边界"带来的工程代价。把它们列清楚,是为了在建模前就判断哪条路走得通,而不是上线后才发现某类查询根本物化不了。

五、已知约束与规避

  • Doris 外表物化视图的一致性窗口 :Doris 暂无法感知除 Hive 外的其他外表数据变更,开启 materialized_view_rewrite_enable_contain_external_table 接受一致性窗口或自行保证外表一致,否则可能出现数据不一致。
  • Snowflake MV 维护成本不可被 Resource Monitor 拦截 :维护走专属的 MATERIALIZED_VIEW_MAINTENANCE 仓库,预算时要单列这一项,不能指望资源监控去限流。
  • Dynamic Tables 不会自动降级全量 :AUTO 刷新模式在创建时解析一次,变更量过大时刷新会失败而非悄悄切换成全量。设计管道时要确保增量刷新路径可行,否则要用全量模式显式声明。
  • 性能数字口径:Doris 的 99% 与 93 倍来自官方博客(TPC-H 100G 单节点测试、湖仓外表场景),是特定测试环境下的结果,不是所有负载的承诺值,引用时保留口径。
  • Snowflake DT 的增量 join 边界:INNER / CROSS 全支持,OUTER 仅等值谓词支持、非等值不支持,LATERAL 不支持(FLATTEN 除外);写多表 DT 前先核对 join 类型是否落在增量刷新支持清单内,否则会被迫走全量。

六、FAQ

Q1:Doris 异步物化视图支持哪些聚合能力?

支持 GROUPING SETS / ROLLUP / CUBE,以及基于 bitmap 类的 COUNT DISTINCT;多表 join 与嵌套物化视图改写也在支持范围内,这使其能覆盖从单表聚合到多表分层建模的多数场景。

Q2:Snowflake Dynamic Table 的 TARGET_LAG 如何设定才合理?

TARGET_LAG 用于声明数据新鲜度目标,例如 '10 minutes',刷新会按该延迟目标调度。设定时应结合上游变更频率与下游容忍延迟,过紧会增加刷新开销,过松则影响数据时效;多表管道官方建议优先使用 Dynamic Table。

Q3:Doris 侧如何确认物化视图已经命中改写?

通过查看执行计划确认查询被改写为命中视图,并可用 SELECT * FROM tasks("type"="mv") 观察刷新任务状态与资源消耗;透明改写自 2.1.5 起默认开启,原始查询无需改动。

Q4:Snowflake MV 的单表限制具体指什么?

Snowflake Materialized View 限定为单表(不支持 join),且不支持窗口函数与 COUNT DISTINCT,也不支持嵌套子查询;这些限制使其只适合单表预聚合这类窄场景,复杂管道需改用 Dynamic Table。

Q5:Doris 与 Snowflake 在刷新资源管控上的核心差异是什么?

Doris 可用 workload_group 将构建与刷新资源隔离,避免挤占在线查询算力;Snowflake MV 维护走专属的 MATERIALIZED_VIEW_MAINTENANCE 仓库且 credits 不受 Resource Monitor 管控,Dynamic Table 则可把 Resource Monitor 挂到分配仓库上。

以上事实均来自下列官方文档与公开材料,引用时建议保留原始 URL 与发布时间,便于复核口径。

测试结论出处(参考来源)

相关推荐
分布式存储与RustFS1 小时前
可观测性数据落进对象存储:Proscia 案例拆解与 ClickHouse 自托管配置
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
fb_123452 小时前
K8s动态卷供应实战_StorageClass与LocalPath_NFS双Provisioner
云原生·容器·kubernetes
时间售卖铺4 小时前
Docker私有仓库搭建与实战指南
运维·docker·云原生·容器
分布式存储与RustFS4 小时前
Kafka 分层存储落地指南:冷 Segment 自动落到 RustFS 对象存储
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
Z21-X4 小时前
云原生运维实战笔记:华为云计算与网络类服务全景解析
运维·笔记·学习·云原生·华为云
孔令飞5 小时前
AI 岗位类别、要求、技能及学习路线
云原生·go·ai编程
SelectDB20 小时前
Doris 异步物化视图实战:与 Snowflake MV / Dynamic Tables 分层建模对照
大数据·数据库·云原生
阿里云云原生21 小时前
从长程 Agent 到 Super-agent,解锁更多场景
云原生
水无痕simon1 天前
4、Eureka服务端安装
云原生·eureka