alitrack

不用流数据库,也能在数据湖上做增量物化视图

群里有人问:DuckDB 能不能像 RisingWave 那样做增量物化视图?

结论很简单——DuckDB 根本没有 CREATE MATERIALIZED VIEW,也没有增量刷新机制。它的物化就是用 CREATE OR REPLACE TABLE AS SELECT 全量重建。

但这引出了一个更有意思的发现:不需要流数据库,也能在数据湖上实现相当好的增量物化视图。而且开源方案比我想象的丰富得多。


● ● ●

先搞清楚一个问题:DuckDB 为什么不做增量物化视图?

DuckDB 是嵌入式 OLAP 引擎。它的执行模型是批处理列存向量化——每条 SQL 语句是一个独立事务,跑完就结束。没有持久化算子状态,没有变更传播 DAG,没有 epoch 协调。

而真正的增量物化视图需要什么?

  • 长生命周期有状态算子(HashAgg 内部存分组计数,HashJoin 存双端索引)
  • 变更捕获机制(CDC/trigger,感知 INSERT/UPDATE/DELETE)
  • 一致性协议(barrier/checkpoint,保证 MV 与源表快照一致)

这是流处理引擎的基础设施,跟 DuckDB 的架构几乎正交。所以 DuckDB 核心团队多年未实现这个功能,不是不做,是不匹配。

● ● ●

那怎么办?三条路线

我把目前开源世界里数据湖 + 增量物化视图的方案分成了三条路线:

路线一:Iceberg-native(物化结果写回 Iceberg,任何引擎都能读)

这是我最看好的方向。核心思路是利用 Iceberg 的 snapshot 元数据做变更检测,计算 delta 写回 Iceberg 表——这样物化结果也是标准 Iceberg 表,不锁死在任何引擎上。

方案
计算引擎
增量方式
成熟度
Floe
DuckDB 默认 / Flink 可选
分区级增量 + snapshot-diff
v0.1,设计最先进
iceberg-ivm
Trino
元数据检测 + MERGE
可用,最轻量
OpenIVM + DuckLake
DuckDB
DBSP 代数→SQL 编译
POC
AWS Glue Iceberg MV
Spark 3.5.6+
全量+增量
GA,AWS only

Floe 是最值得关注的一个。它做的事情就是 "Snowflake Dynamic Tables 的开源版"。你声明一个 SQL 查询和刷新模式,floe watch 监控 Iceberg snapshot 变化,只对被修改的分区做增量计算,结果写回 Iceberg。底层计算引擎可插拔——本地用 DuckDB 跑,规模大了切 Flink。

iceberg-ivm 更极简。服务本身不动数据——它只读 Iceberg 的 $snapshots 和 $all_entries 元数据表(~50ms),发现变更后把增量 SQL 发给 Trino 执行 MERGE INTO。适合已有 Trino + Iceberg 基础设施的团队。

路线二:引擎内置 MV(物化结果存在引擎内部)

StarRocks 和 Doris 都有异步物化视图,支持 Iceberg/Hudi/Delta 外部 Catalog。物化视图在引擎内部做分区级增量刷新,带自动查询重写。

方案
增量方式
自动查询重写
Iceberg 读
Iceberg 写回
StarRocks
异步分区增量
✅
✅
❌
Apache Doris
异步分区增量
✅
✅
❌
ClickHouse
insert 触发增量 / 定时全量
直接查 target
✅
🚧 计划中

这条路的问题是物化结果封闭在引擎内部——你用 StarRocks 建的 MV,Spark 读不了。数据湖的开放性被牺牲了一半。

但如果你整个查询层都用 StarRocks/Doris,这反而是最简单高效的选择。零额外组件,标准 SQL 建 MV,自动增量刷新。

路线三:流引擎(真·实时增量)

RisingWave 和 Feldera 走这条路。Kafka/CDC 过来的数据通过 Actor DAG 连续增量计算,物化结果存在流引擎的状态存储里,也可以 sink 回 Iceberg。

方案
延迟
核心机制
独特性
RisingWave
亚秒
变更传播 Actor DAG
PostgreSQL 兼容
Feldera
亚秒
DBSP 电路
可暂停/恢复/快照

Feldera 特别值得提一句。它不是流引擎,也不是批引擎——它是"增量计算引擎"。你把 SQL 表+View 定义成一个 Pipeline,可以启动、暂停、恢复、查询当前状态。与 RisingWave 的"持续运行流图"模型不同,Feldera 更适合需要中间暂停、回溯验证的场景。


● ● ●

一张图看清关系

数据湖增量物化视图生态关系图

数据湖增量物化视图生态关系图


● ● ●

我的判断

如果你今天要在数据湖上做增量物化视图,最务实的路线是 Iceberg-native。理由很简单:

  1. 01Iceberg 的 snapshot 机制天然适合增量检测
    ——start-snapshot-id / end-snapshot-id 扫描选项让你能精确知道哪些文件发生了变化,不需要自己维护变更日志。
  1. 01Floe 正在填这个坑
    。虽然还是 v0.1,但设计思路非常清晰:声明式 SQL → 自动依赖解析 → 分区级增量 → 写回 Iceberg。这正是 Snowflake Dynamic Tables 的开源版。
  1. 01即使不用 Floe,iceberg-ivm 的模式 50 行代码就能复现
    :读 $all_entries.readable_metrics 找到变更时间范围 → 扩展范围到完整 GROUP BY bucket 边界 → 对受影响分区跑 MERGE INTO。这是我在调研中见到的最优雅的极简方案。
  1. 01
    StarRocks/Doris 成熟但锁引擎。如果你能接受这个代价,选它们没毛病。但要记住:你在数据湖里存数据就是为了不被引擎锁住——建 MV 的时候把它又锁回去,逻辑上是矛盾的。

● ● ●

参考资源

Floe:https://github.com/takasoft/floe

iceberg-ivm:https://github.com/jonasbrami/iceberg-ivm

OpenIVM:https://github.com/ila/openivm

Feldera:https://github.com/feldera/feldera

StarRocks 异步 MV:https://docs.starrocks.io/docs/using_starrocks/Materialized_view

Apache Doris 异步 MV:https://doris.apache.org/docs/4.x/query-acceleration/materialized-view/async-materialized-view/overview

pg_trickle DBSP 对比:https://github.com/grove/pg-trickle/blob/main/docs/research/DBSP_COMPARISON.md

Apache Iceberg MV Spec(社区讨论):https://github.com/apache/iceberg/issues/9048