摘要
物化视图是查询加速的通用手段,但两边能力边界差得不少。Apache Doris 的异步物化视图一套机制覆盖多表 join、嵌套、分区增量刷新与资源管控;Snowflake 把单表加速与多表管道拆成两套机制------Materialized Views 与 Dynamic Tables。本文以实战笔记的写法把建视图、开改写、看监控、排错现场一步一步列清,并给出与 Snowflake 的逐行对照,方便做数据分层建模时选对工具。两边并非简单优劣关系,而是机制划分与适用负载不同;下文把能力清单、成本结构与限制逐条对齐,对照时一眼看到差异落点。
一、先说结论
- Doris 异步物化视图: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 Dynamic Tables:2024-04-29 GA,建议作为新建多表 SQL 管道首选;用
TARGET_LAG声明新鲜度,刷新分 incremental / full,官方明确不因变更量大而自动降级为全量刷新。TARGET_LAG 把"数据要新到什么程度"变成可声明参数。 - 选型落点:单表聚合两边都能做;多表管道、嵌套分层、分区增量、刷新资源管控是差异集中区,也是选型时逐条核对的清单。
二、问题怎么产生
物化视图解决"重复计算":把贵的计算提前算好存下,查询到来直接取,而非每次重跑。但"建了就快"是误解,它有两个易低估的代价------维护成本(刷新耗算力)与能力边界(哪些 SQL 能被物化),这两件事决定一个视图"能不能用、用得起"。
排错现场常遇到:视图建出来,基表一更新查询却没变快,或刷新把在线查询算力吃满。前者是改写没命中,后者是资源没隔离。Snowflake 把单表加速与多表管道拆成两套机制,接入方式与限制清单随之不同;Doris 用一套异步 MV 覆盖从单表聚合到多表分层的多数场景。
还有常被忽略的点:物化视图维护本身耗资源且走独立账单,若维护成本压过查询收益,视图反成负担。比较两套机制不能只看"能不能加速",还要看"维护贵不贵、能不能限"。这也是多表管道选型要先确认刷新模式与资源边界、而非只看"能不能建出来"的原因。
实战里一个常见误判:看到"物化视图能加速"就先建,结果维护账单先爆。正确顺序是先估刷新成本再建------单表聚合且基表更新不频繁,Snowflake MV 或 Doris 异步 MV 都划算;多表管道且基表变更频繁,要把刷新资源隔离(Doris 用 workload_group、Snowflake DT 绑独立仓库)写进设计,否则在线查询会被刷新拖垮。
三、怎么做
按"建视图、开改写、看监控"与"Snowflake 两套写法"两路,把接入落到具体语法,每段都给现场感,遇到异常直接照着排查。
3.1 Doris:多表聚合 + 分区增量 + 资源管控
一个覆盖多表 join 的视图,可同时指定分区增量刷新与构建资源组:
vbnet
CREATE MATERIALIZED VIEW region_rev_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 把构建与正常查询隔开,避免大视图刷新挤掉在线查询算力;分区增量刷新让每天只动的分区重算,其余原样保留,而非整表推倒重来。排错现场:构建把在线查询拖垮,先确认 PROPERTIES 里 workload_group 是否真的绑了独立资源组。
3.2 透明改写与监控
透明改写 2.1.5 起默认开启,原始查询无需改动即可被优化器改写为命中该视图:
sql
-- Doris 2.1.5 起透明改写默认开启;如需显式开启:
SET enable_materialized_view_rewrite = true;
-- 查看物化视图刷新任务状态与资源消耗
SELECT * FROM tasks("type"="mv")
WHERE MvName = 'region_rev_mv'
ORDER BY CreateTime DESC;
排错现场:改写没命中先确认 enable_materialized_view_rewrite 状态,再用 tasks("type"="mv") 看刷新是否成功;外表场景还需确认一致性窗口开关是否打开。
3.3 Snowflake:单表 MV 与多表 DT 两套写法
Snowflake 的 Materialized View 仅支持单表、不支持 join;多表管道用 Dynamic Table:
sql
-- Snowflake Materialized View:仅支持单表、不支持 join
CREATE MATERIALIZED VIEW mv_daily_sales
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 dt_sales_pipeline
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 显式绑定刷新算力。实际项目里若已有单表聚合层,把它物化成 MV,再往上叠多表汇总交给 DT,两层之间靠 TARGET_LAG 串起新鲜度。
3.4 监控视图
除 tasks("type"="mv") 外,Doris 还提供 mv_infos 查看视图元数据与状态:
sql
-- 查看物化视图元数据与刷新状态
SELECT * FROM mv_infos
WHERE MvName = 'region_rev_mv';
Snowflake 侧对应 DYNAMIC_TABLE_REFRESH_HISTORY 查看 DT 刷新历史,刷新失败原因优先到这张历史表排查,而非只看仓库账单。
3.5 参数速查表
| 参数名 | 建议值 | 作用 | 适用场景 |
|---|---|---|---|
| workload_group | mv_build_group | 限制构建与刷新资源占用 | 大视图刷新避免挤占在线查询 |
| enable_materialized_view_rewrite | true | 透明改写命中异步视图 | 2.1.5 起默认开启 |
| REFRESH AUTO ON MANUAL | ON MANUAL | 声明手动/自动刷新策略 | 按刷新频率需求选择 |
| materialized_view_rewrite_enable_contain_external_table | true | 允许外表参与透明改写 | 湖仓外表加速(接受一致性窗口) |
| TARGET_LAG | '10 minutes' | 声明 Dynamic Table 新鲜度 | Snowflake 多表管道 |
| replication_num | 1 | 设置视图副本数 | 测试 / 小集群环境 |
四、维度对照表
逐行列出八项关键事实,重点看"多表 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 外表物化视图一致性窗口:暂无法感知除 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 类型是否落在增量刷新支持清单,否则被迫走全量。
排错时还有一个细节:Doris 侧外表 MV 改写没命中,优先确认一致性窗口开关而非直接怀疑查询;Snowflake 侧 DT 刷新慢或失败,先看 DYNAMIC_TABLE_REFRESH_HISTORY 的失败原因字段,别只盯仓库账单。
六、FAQ
Q1:Snowflake MV 与 Dynamic Tables 怎么选? 单表聚合加速用 Materialized View;多表 SQL 管道用 Dynamic Tables,官方按此边界给建议。
Q2:Doris 物化视图刷新能限制资源吗? 能。建视图时 PROPERTIES 指定 workload_group,构建与刷新只占用该组资源,不影响正常查询。
Q3:Snowflake MV 维护成本能靠 Resource Monitor 拦住吗? 不能。MV 维护走专属仓库,明确不受 Resource Monitor 管控,需在成本核算单列项。
Q4:Dynamic Tables 刷新失败会自动降级全量吗? 不会。官方明确 AUTO 模式不因变更量大而切换刷新方式,失败即失败,需显式选全量模式或修正增量路径。
Q5:外表物化视图在 Doris 侧要注意什么? 除 Hive 外外表变更暂不可感知,需打开允许外表改写的开关并接受一致性窗口,或自行保证外表数据时效,否则透明改写可能返回过期结果。
最后给一个落地节奏建议:物化视图先在小表验证改写命中,再用 tasks("type"="mv") 看刷新耗时与资源占用,确认可控后再上多表分层;资源隔离(workload_group)和刷新模式(增量/全量)在创建时就定好,上线后再调成本高。
以上事实来自下列官方文档与公开材料,引用保留原始 URL 与发布时间便于复核。