Featured image of post DuckDB Iceberg 新特性:MERGE INTO、ALTER TABLE 与分区转换全面支持

DuckDB Iceberg 新特性:MERGE INTO、ALTER TABLE 与分区转换全面支持

DuckDB v1.5.3 中 DuckDB-Iceberg 扩展带来 MERGE INTO 合并写入、ALTER TABLE 模式演化、bucket/truncate 分区转换和 Iceberg V3 支持等核心新功能,全面补齐数据湖操作能力。

概述

2026 年 5 月 29 日,DuckDB 官方发布了一篇重磅博客文章——“New DuckDB-Iceberg Features in v1.5.3”。尽管团队正在全力开发 DuckLake v1.0 和 Quack 协议,但 DuckDB-Iceberg 扩展的更新从未停歇。这篇文章实际上是 2025 年 11 月"Iceberg 写入"系列博文的下篇,重点展示了 v1.5.3 中一系列令数据工程师兴奋的新功能。

本文带你深入体验 DuckDB-Iceberg 扩展的最新特性,从 MERGE INTO 合并写入到 ALTER TABLE 模式演化,从分区转换到 Iceberg V3 规范支持,全方位展示 DuckDB 在数据湖领域的全面进化。

前置准备:连接到 Iceberg REST Catalog

在使用这些新功能之前,你需要先连接到一个 Iceberg REST Catalog。DuckDB 支持多种 Catalog 后端,包括 Apache Polaris、Lakekeeper 以及 Amazon S3 Tables。

连接方式非常简洁:

ATTACH 'warehouse_name' AS my_datalake (
    TYPE iceberg,
    other options
);

这一条语句就将你的数据湖仓库挂载为 DuckDB 中的一个逻辑 catalog,后续所有 Iceberg 操作都通过 my_datalake.default.table_name 的方式访问。

特性一:MERGE INTO — 数据湖的 Upsert 操作

在数据工程领域,合并写入(Merge / Upsert) 是最常见也最复杂的操作之一。Iceberg 等 Lakehouse 格式不支持主键约束,因此 DuckDB 的 MERGE INTO 语句成为了操作 Iceberg 表的推荐方式。

v1.5.3 之前,你只能通过 INSERT + DELETE 来模拟 upsert,现在你可以用一条语句完成:

-- 创建示例表
CREATE TABLE my_datalake.default.people (
    id INTEGER,
    name VARCHAR,
    salary FLOAT
);

INSERT INTO my_datalake.default.people
    VALUES (1, 'John', 92_000.0), (2, 'Anna', 100_000.0);

现在执行合并写入——更新 John 的薪资,同时插入新员工 Sarah:

MERGE INTO my_datalake.default.people AS target
USING (
    FROM (VALUES
        (1, 'John', 105_000.0),
        (3, 'Sarah', 95_000.0)
    ) t(id, name, salary)
) AS upserts
ON (upserts.id = target.id)
WHEN MATCHED THEN UPDATE
WHEN NOT MATCHED THEN INSERT;

查询结果:

┌───────┬─────────┬──────────┐
│  id   │  name   │  salary  │
│ int32 │ varchar │  float   │
├───────┼─────────┼──────────┤
│     1 │ John    │ 105000.0 │
│     2 │ Anna    │ 100000.0 │
│     3 │ Sarah   │  95000.0 │
└───────┴─────────┴──────────┘

更强大的是,你还可以在同一个语句中执行删除操作:

MERGE INTO my_datalake.default.people AS target
USING (VALUES (2)) AS deletes(id)
ON (deletes.id = target.id)
WHEN MATCHED THEN DELETE;

底层实现上,MERGE INTO 使用 merge-on-read 语义,将位置删除(positional deletes)写入 Iceberg 表,保证了数据的最终一致性。

特性二:ALTER TABLE — Iceberg 表的模式演化

Iceberg 格式的核心优势之一就是模式演化(Schema Evolution)。在 v1.5.3 之前,DuckDB 对 Iceberg 表的 ALTER 操作是完全不支持的,这在数据工程场景中是一个重大限制。

v1.5.3 带来了全面的 ALTER TABLE 支持:

-- 创建初始表
CREATE TABLE my_datalake.default.simple_table AS
    FROM (VALUES
        (1, 'Andy'),
        (2, 'Bob'),
        (3, 'Claire'),
        (4, 'Mr. Duck')
    ) t(col1, col2);

-- 重命名表
ALTER TABLE my_datalake.default.simple_table
    RENAME TO renamed_table;

-- 添加新列
ALTER TABLE my_datalake.default.renamed_table
    ADD COLUMN col3 DOUBLE;

-- 重命名列
ALTER TABLE my_datalake.default.renamed_table
    RENAME COLUMN col2 TO name;

-- 删除列
ALTER TABLE my_datalake.default.renamed_table
    DROP COLUMN col3;

-- 设置 format-version
ALTER TABLE my_datalake.default.renamed_table
    SET ('format-version' = 3);

在后台,每个 ALTER TABLE 语句都会更新 Iceberg 表的 current-schema-id。其他 Iceberg 引擎只需调用 LoadTableInformation 端点即可立即看到变更。由于 Iceberg 的模式演化是纯元数据操作,不需要重写任何数据文件,因此效率极高。

特性三:Bucket 与 Truncate 分区转换

Iceberg 规范定义了多种分区转换(Partition Transforms),决定了数据文件在磁盘上的布局。v1.5.3 带来了 buckettruncate 两种转换的全面支持。

Bucket 分区

bucket(N, col) 将列的值哈希到 N 个桶中,适用于高基数列的稳定分区:

CREATE TABLE my_datalake.default.events (
    event_id BIGINT,
    user_id BIGINT,
    country VARCHAR,
    payload VARCHAR
)
PARTITIONED BY (bucket(16, user_id), truncate(2, country));

INSERT INTO my_datalake.default.events
    VALUES
        (1, 1001, 'United States', 'click'),
        (2, 1002, 'United Kingdom', 'view'),
        (3, 1003, 'Germany', 'click'),
        (4, 1004, 'Netherlands', 'view');

Truncate 分区

truncate(W, col) 将列的值按前 W 个字符(或数值向下舍入到 W 的倍数)进行分组,适用于基于前缀的分区策略。

你可以使用 iceberg_metadata() 函数查看分区结果:

SELECT file_path, record_count
FROM iceberg_metadata(my_datalake.default.events)
WHERE content = 'EXISTING';

特性四:Iceberg Schema Properties

Iceberg 支持在 Schema(命名空间)级别附加任意键值对的属性。这些属性通常用于记录所有者信息、描述、默认存储位置等元数据。

DuckDB 提供了三个内置函数来管理这些属性:

-- 设置 Schema 属性
CALL set_iceberg_schema_properties(my_datalake.default, {
    'owner': 'analytics-team',
    'description': 'Default analytics schema'
});

-- 查看 Schema 属性
SELECT * FROM iceberg_schema_properties(my_datalake.default);
-- ┌─────────────┬──────────────────────────┐
-- │     key     │          value           │
-- │   varchar   │         varchar          │
-- ├─────────────┼──────────────────────────┤
-- │ owner       │ analytics-team           │
-- │ description │ Default analytics schema │
-- └─────────────┴──────────────────────────┘

-- 删除 Schema 属性
CALL remove_iceberg_schema_properties(
    my_datalake.default,
    ['description']
);

Schema 属性通过 Iceberg REST Catalog 写入,其他 Iceberg 引擎可以立即看到这些变更。

特性五:Iceberg V3 规范支持

Iceberg V3 规范引入了一系列新特性,DuckDB-Iceberg 现在对读写都提供了完整支持。这包括:

  • Schema Metadata:更丰富的表元数据管理
  • Identity Partitioning:更直接的分区策略
  • V3 特有功能:更多高级数据湖管理能力

这些特性的加入,让 DuckDB 成为支持 Iceberg V3 最全面的开源工具之一。

与传统数据湖工具的对比

特性DuckDB-Iceberg v1.5.3Apache SparkPresto/Trinodbt
MERGE INTO✅ 原生支持✅ 支持⚠️ 有限⚠️ 需 SQL
ALTER TABLE 模式演化✅ 全面支持⚠️ 部分⚠️ 只读❌ 不支持
Bucket 分区转换✅ 支持✅ 支持✅ 支持❌ 不支持
Truncate 分区转换✅ 支持✅ 支持⚠️ 有限❌ 不支持
Schema Properties✅ 支持❌ 不支持❌ 不支持❌ 不支持
安装部署⭐ 零依赖单文件❌ 重量级集群⚠️ 需要集群⚠️ 需要引擎
小数据量性能⭐ 极快❌ 启动开销大⚠️ 中等⚠️ 依赖引擎
内存使用⭐ 100MB-1GB❌ GB 级⚠️ 几百 MB⚠️ 依赖引擎

实战场景:增量数据管道

以下是一个完整的增量数据管道示例,展示了如何在实际生产中使用这些新特性:

-- 1. 挂载 Iceberg 仓库
ATTACH 's3://my-warehouse' AS warehouse (
    TYPE iceberg,
    S3_REGION 'us-east-1',
    AWS_ACCESS_KEY_ID '...',
    AWS_SECRET_ACCESS_KEY '...'
);

-- 2. 创建带分区的增量表
CREATE TABLE IF NOT EXISTS warehouse.default.user_events (
    event_id BIGINT,
    user_id BIGINT,
    event_type VARCHAR,
    payload VARCHAR,
    created_at TIMESTAMP
)
PARTITIONED BY (bucket(8, user_id), truncate(2, event_type));

-- 3. 每日增量 MERGE
MERGE INTO warehouse.default.user_events AS target
USING (
    SELECT * FROM read_parquet('/data/daily/2026-06-07/*.parquet')
) AS source
ON (source.event_id = target.event_id)
WHEN MATCHED THEN UPDATE SET
    event_type = source.event_type,
    payload = source.payload
WHEN NOT MATCHED THEN INSERT;

-- 4. 验证数据
SELECT
    user_id,
    COUNT(*) AS event_count,
    SUM(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) AS purchases
FROM warehouse.default.user_events
WHERE created_at >= '2026-06-01'
GROUP BY user_id
ORDER BY purchases DESC;

变现建议

掌握 DuckDB-Iceberg 新特性后,你可以在以下几个方向实现商业化变现:

  1. 数据咨询服务:为企业搭建基于 DuckDB + Iceberg 的轻量级数据湖,替代昂贵的 Spark 集群。中小企业通常没有大数据工程师,DuckDB 的低门槛恰好解决了这一痛点。按项目收取 5-15 万元不等的咨询费。

  2. 数据分析 SaaS 产品:利用 DuckDB 的 MERGE INTO 和增量写入能力,快速构建面向电商、金融等领域的实时数据分析面板。可以按订阅制收费,月费 99-499 元/用户。

  3. 企业培训与认证:开设 DuckDB-Iceberg 实战课程,涵盖 MERGE INTO、分区策略、性能调优等核心技能。线上课程定价 299-999 元,企业内训定价 2-5 万元/场。

  4. 开源商业化:围绕 DuckDB-Iceberg 构建企业级工具链(如数据质量监控、自动化管道编排),采用开源核心 + 商业增值的模式,参考 DataCater 和 dbt Labs 的路径。

  5. 数据集成中间件:利用 DuckDB 的多格式读取能力和 Iceberg 的标准化写入,开发面向 CSV/Parquet/JSON 到 Iceberg 的 ETL 中间件,按调用量或订阅收费。

总结

DuckDB v1.5.3 中的 DuckDB-Iceberg 扩展更新,标志着 DuckDB 在数据湖领域从"查询引擎"向"完整数据湖平台"的转型。MERGE INTO 补齐了 upsert 能力的最后一块拼图,ALTER TABLE 实现了真正的模式演化,分区转换和 Schema Properties 则让数据湖的精细化管理成为可能。

对于正在寻找轻量级数据湖方案的个人开发者和中小企业来说,DuckDB-Iceberg 的组合几乎是目前最佳选择——零配置、高性能、完全开源。


本文基于 DuckDB 官方博客 New DuckDB-Iceberg Features in v1.5.3 编写,发布于 2026 年 5 月 29 日。

📺 Watch video tutorials → DuckDB Lab YouTube

Subscribe for more DuckDB & AI automation tutorials

使用 Hugo 构建
主题 StackJimmy 设计