由 John Doe 六月 22, 2026
DuckLake 使用标准 SQL 数据库统一管理所有元数据,摒弃复杂的文件型元数据体系,同时底层数据仍采用 Parquet 等开放格式存储,以此简化湖仓架构,实现更高可靠性、更快查询速度与更低运维成本。

目录
背景介绍
BigQuery、Snowflake 等创新数据系统证明:在存储资源虚拟化、按需采购的当下,存储与计算分离是极具价值的架构思路。二者可独立弹性扩缩容,企业无需为长期闲置的离线数据表采购昂贵专用数据库硬件。
与此同时,市场诉求倒逼数据系统采用 Parquet 这类开放存储格式,避免被单一厂商绑定、形成数据锁定。基于对象存储(S3 等)+ Parquet 构建的数据湖一度被视作最优解,不少团队认为传统数据库已无存在必要。
但很快,这套方案暴露严重短板:
简单追加数据仅需往文件夹新增文件即可实现;但数据修改、更新、删除等操作,只能依靠大量复杂、易出错的自定义脚本实现,既无法保障数据正确性,更不具备数据库 ACID 事务能力。
Iceberg 与 Delta Lake
为解决数据湖的数据变更难题,业界诞生两大主流开放表格式标准:Apache Iceberg、Linux 基金会 Delta Lake。二者设计初衷一致:在基于对象存储开放文件格式的基础上,为数据湖补齐数据库核心能力,也就是 “湖仓一体”。典型能力包括跨引擎数据共享等。
以 Iceberg 为例:依靠多层 JSON、Avro 元数据文件定义表结构、数据快照、每个快照对应的 Parquet 数据文件集合。
Iceberg 表架构分层
- 元数据层:元数据根文件 → 清单列表 → 清单文件
- 数据层:Parquet 数据文件
但两种格式都存在难以规避的底层缺陷:
对象存储的一致性机制不稳定,想要原子替换表最新版本指针(ACID 中的原子性 A)难度极高;同时 Iceberg、Delta Lake 原生仅能单表管理,企业普遍存在多表统一管控的需求。
元数据目录(Catalog)的诞生
业界给出的解决方案是新增一层目录服务:目录后端对接数据库,统一记录所有数据表的存储路径;同时维护一张特殊数据表,每行对应一张业务表,存储该表当前版本号。借助数据库的事务能力更新版本号,实现多客户端读取统一最新视图。
Iceberg 目录架构分层
- 数据库目录层:记录表名、当前元数据指针
- 元数据层:元数据根文件 → 清单列表 → 清单文件
- 数据层:Parquet 数据文件
既然要用数据库,为何不彻底重构?
Iceberg、Delta Lake 的设计初衷本是无需依赖数据库,为此设计者做了大量妥协,把表读写、更新所需全部信息编码存入对象存储文件中:
1. Iceberg 每一份根元数据文件都会完整存储全量快照、表结构信息;每次数据变更都生成全新完整历史文件;
2. 为避免对象存储读写大量小文件拖慢性能,元数据被迫拆分为双层清单文件做批量聚合;
3. 小数据变更场景长期无成熟解决方案,配套的清理、合并逻辑复杂,开源实现支持不完善,甚至催生大量专门解决高频变更数据管理的创业公司。
前文提到,Iceberg/Delta 为保证一致性,最终仍不得不引入数据库作为目录后端;但它们没有基于 “已有数据库” 这个核心前提,重新优化整体架构与技术栈,大量妥协设计依然存在。
DuckLake 方案
DuckDB 团队本身深耕数据库领域,数据库本就是安全、高效管理海量数据集的成熟工具。既然湖仓架构中已经引入数据库,完全可以用它接管全部表元数据!
底层真实业务数据依旧存放在对象存储的 Parquet 开放文件中,享受无限扩容、无厂商锁定的优势;元数据则交给数据库统一管理,效率、易用性大幅提升。
这一思路与谷歌 BigQuery(后端 Spanner)、Snowflake(后端 FoundationDB)不谋而合,区别仅在于 DuckLake 底层使用开放数据格式。
DuckLake 架构分层
- 数据库 & 元数据目录层:存储表、快照、统计信息、文件映射等全部元数据
- 数据层:Parquet 数据文件
DuckLake 核心设计理念
DuckLake 推出全新开源表格式 DuckLake,重新定义湖仓架构,基于两个客观事实:
- 对象存储存放 Parquet 等开放格式数据,是实现无限扩容、规避厂商锁定的最优方案;
- 元数据管理是复杂、强关联的数据治理工作,交由数据库管理系统处理最为合适。
DuckLake 将所有元数据结构存入 SQL 数据库,目录、表相关元数据全部关系化存储。整套格式由一组关系表、配套纯 SQL 事务逻辑定义,覆盖建表、改表、数据增删改全流程。
核心优势:
- 支持任意数量数据表,可实现跨表事务;
- 完整支持视图、嵌套复杂类型、事务性表结构变更等数据库高级特性;
- 依托数据库外键约束保障 ACID 一致性(一致性 C),例如杜绝重复快照 ID 等异常。
DuckLake 内置元数据表(核心结构)
包含一系列标准化关系表:
- table:表基础信息(表 ID、UUID、名称、快照区间、结构 ID)
- column:字段基础定义(字段名、类型、默认值、是否允许空值等)
- table_stats:表级统计(总行数、总文件大小)
- table_column_stats:字段级全局统计(空值、极值、是否含 NaN)
- data_file:数据文件记录(Parquet 路径、记录数、文件大小、分区 ID)
- delete_file:删除标记文件记录
- file_column_statistics:单文件字段统计
- snapshot:快照记录表(快照 ID、时间、结构版本、文件自增 ID)
- schema:表结构版本记录
用户可自由选择底层 SQL 数据库,仅需满足:支持 ACID 事务、主键约束、标准 SQL 语法。内置元数据表结构极简,最大化兼容各类数据库。
示例:插入数据完整 SQL 事务流程
执行语句:INSERT INTO demo VALUES (42), (43);
系统自动开启完整事务,批量执行以下 SQL 写入元数据库:
-
写入新 Parquet 文件路径至 ducklake_data_file;
-
更新全局表统计信息(总行数、文件总大小)至 ducklake_table_stats;
-
更新字段全局统计(最大值、最小值)至 ducklake_table_column_stats;
-
写入单文件字段统计数据至 ducklake_file_column_statistics;
-
创建新版本快照存入 ducklake_snapshot;
-
记录本次快照变更类型至 ducklake_snapshot_changes;
最后提交事务。
注:真实 Parquet 文件写入操作在事务执行前完成,无论插入多少条数据,这套元数据事务开销恒定且极低。
DuckLake 三大核心设计原则:简洁、弹性、高性能
简洁性
1. 本地轻量化部署:只需安装带 ducklake 扩展的 DuckDB,元数据目录直接存成本地 DuckDB 文件,适配本地测试、开发、原型验证场景。
2. 存储兼容无侵入:数据文件均为不可变文件,不支持原地修改、不复用文件名,兼容本地磁盘、NAS、S3、微软 Azure Blob、谷歌 GCS 等几乎所有存储;创建元数据表时指定存储前缀(如s3://mybucket/mylake/)即可。
3. 目录数据库选型灵活:任何支持 ACID、主键的成熟 SQL 库均可作为目录存储,企业现有运维经验可直接复用,无需新增运维组件;托管 PostgreSQL、托管 DuckDB 均可直接接入。
4. 无额外文件 / 组件依赖:无需维护 Avro、JSON 元数据文件,无需独立目录服务、额外 API 网关,整套元数据交互仅靠标准 SQL 实现,学习成本极低。
5. 迁移成本极低:切换底层目录数据库无需迁移业务数据,标准化极简元数据表结构降低迁移门槛。
弹性扩展
架构三层职责彻底解耦,各自无限扩容:
1. 存储层:业务数据存于专用对象存储,容量无上限;
2. 计算层:任意数量计算节点并发读写目录数据库,再独立读写远端存储,算力横向无限扩展;
3. 元数据目录层:仅处理计算节点下发的元数据事务,流量远小于真实数据读写;支持平滑迁移底层数据库(如 PostgreSQL 升级至 Spanner),单套 PostgreSQL 后端即可支撑数百 TB 数据、数千并发计算节点。
这套分层架构已被 BigQuery、Snowflake 验证,可稳定承载超大规模数据集。
高性能
Iceberg、Delta Lake 最大性能痛点:单次查询需要大量串行文件 IO,多次对象存储 HTTP 请求往返,事务提交关键路径耗时久、冲突频发、冲突恢复成本高;缓存只能缓解热点数据问题,同时增加架构复杂度。
DuckLake 统一元数据存于 SQL 数据库,大幅优化性能:
1. 单次元数据查询完成裁剪:读取表时仅向目录数据库发送一条 SQL,数据库基于表结构、分区、统计信息完成文件裁剪,直接返回需要读取的文件列表;无需多次访问存储、拼接元数据状态,规避 S3 限流、请求失败、存储一致性延迟导致文件不可见等问题。
2. 优化小变更、高并发变更场景
- 大幅减少存储侧小文件:无需为微小变更生成全新快照、清单文件;支持将少量变更直接内嵌存入元数据库,避免大量小文件,实现亚毫秒级写入,简化文件合并、清理流程;
- 事务关键路径极短:数据变更仅两步:① 预写数据文件至存储;② 执行单次 SQL 事务更新元数据库。冲突窗口大幅缩短,依托数据库原生冲突处理能力,支持极高并发事务;PostgreSQL 单库每秒可处理数千事务,上千节点每秒追加数据也可稳定运行。
3. 海量快照支持:快照仅为元数据库新增少量行,无需主动清理;快照可关联 Parquet 文件局部片段,快照数量可远超物理文件数,支持百万级快照长期留存。
DuckLake 完整功能清单
- 全量标准 SQL 支持:复用 DuckDB 完整 SQL 能力;
- 数据变更:高效追加、更新、删除;
- 多 Schema、多表统一管理:一套元数据结构承载任意数量库、表;
- 跨表 ACID 事务:库、表、数据变更全局事务隔离;
- 复杂嵌套数据类型:列表、多层嵌套结构完整支持;
- 全量表结构演进:新增 / 删除字段、修改字段类型均支持;
- 库级时间旅行与回滚:基于快照隔离,可查询历史任意时间点数据;
- 增量扫描:仅读取两个快照间的变更数据;
- SQL 视图:懒加载逻辑视图;
- 透明分区与数据裁剪:内置分区、文件级统计,提前过滤扫描数据;
- 事务性 DDL:建库、建表、改结构、删表全部事务保障;
- 大幅减少文件合并需求:相比同类格式合并频次显著降低,支持快照高效合并;
- 变更内嵌存储:少量数据变更可直接存入元数据库,避免生成大量小文件;
- 数据加密:存储侧 Parquet 文件可加密,密钥由元数据库统一管理;
- Iceberg 兼容:存储层数据文件、位置删除文件与 Apache Iceberg 完全兼容,仅迁移元数据即可互通。
DuckDB ducklake 扩展插件
定义存储格式简单,落地稳定运行难度高。本次同步发布 DuckDB 计算节点实现 ——ducklake扩展插件,完整实现上述 DuckLake 格式全部能力。
- 开源协议:MIT 协议,知识产权归属非营利组织 DuckDB 基金会;
- 架构价值:将单机 DuckDB 升级为支持集中式数仓的分布式计算引擎,无需额外配套组件;企业可搭建集中式元数据库 + 对象存储(AWS RDS+S3 或自建),在员工电脑、应用服务器、无服务函数等海量设备上运行带 ducklake 扩展的 DuckDB 实例。
插件兼容性
- 本地模式:使用本地 DuckDB 文件作为元数据库;
- 远端集中目录:兼容 DuckDB 可对接的所有外部数据库(PostgreSQL、SQLite、MySQL、MotherDuck);
- 文件存储:兼容 DuckDB 全部存储驱动(本地文件、S3、Azure Blob、GCS 等);
- 共存兼容:不替代 DuckDB 原有 Iceberg、Delta Lake 支持,可作为二者本地加速缓存使用。
版本要求
DuckDB v1.3.0(代号 Ossivalis)及以上版本内置支持 DuckLake。
安装步骤
- 安装 DuckDB 客户端;
- 启动 DuckDB;
- 执行命令:
INSTALL ducklake;
使用示例
1. 挂载 DuckLake 库
通过ATTACH命令初始化:
ATTACH 'ducklake:metadata.ducklake' AS my_ducklake;
本地模式下:元数据表存入metadata.ducklake文件;业务 Parquet 文件自动存放至同级metadata.ducklake.files文件夹,支持绝对路径配置。
2. 建表与插入数据
CREATE TABLE my_ducklake.demo (i INTEGER);
INSERT INTO my_ducklake.demo VALUES (42), (43);
使用USE切换默认库:USE my_ducklake;
3. 查询数据表
FROM my_ducklake.demo;
4. 查看生成的 Parquet 文件
FROM glob('metadata.ducklake.files/main/demo/*');
输出单条 Parquet 文件路径。
5. 删除数据
DELETE FROM my_ducklake.demo WHERE i = 43;
FROM my_ducklake.demo;
查询结果仅保留 42;文件夹新增后缀-delete.parquet的删除标记文件。
6. 时间旅行(快照查询)
通过ducklake_snapshots()查看全部快照:
FROM ducklake_snapshots('my_ducklake');
输出快照 ID、快照时间、结构版本、变更记录。
使用AT语法读取历史版本:
FROM my_ducklake.demo AT (VERSION => 2);
读取快照 2,可恢复已删除的 43;也可替换为时间戳TIMESTAMP按时间回溯。
7. 查看快照间增量变更
FROM ducklake_table_changes('my_ducklake', 'main', 'demo', 2, 3);
清晰展示快照 2 插入两条数据、快照 3 删除一条数据。
8. 事务回滚示例
BEGIN TRANSACTION;
DELETE FROM my_ducklake.demo;
FROM my_ducklake.demo; -- 当前查询无数据
ROLLBACK;
FROM my_ducklake.demo; -- 回滚后数据恢复
总结
本文完整介绍了基于纯 SQL 构建的全新湖仓表格式 DuckLake 的设计背景与架构逻辑。如果你需要一套简洁、弹性、高性能的湖仓存储方案,不妨尝试 DuckLake,我们期待看到大家的落地实践场景!