原文地址https://ducklake.select/2026/04/13/ducklake-10/DuckLake v1.0 发布DuckDB 团队 | 2026-04-13 ·TL;DR我们很高兴地发布 DuckLake v1.0一个可用于生产环境的湖仓一体格式规范。其参考实现即ducklakeDuckDB 扩展自今日起在 DuckDB v1.5.2 中可用。在 2025 年 5 月我们发布了 DuckLake 宣言解释了促使我们开发 DuckLake 的动机。这里快速回顾一下我们基本上概述了在我们看来将湖仓一体的所有元数据存储在数据库中而不是分散在对象存储的各个文件中要有意义得多。这就是我们创建 DuckLake 的原因。提示那份宣言更有说服力我们建议你阅读一下今天我们很高兴地宣布 DuckLake v1.0 发布距离我们发布规范的初稿已近一年。这是一个可用于生产环境的版本并保证向后兼容性。DuckLake v1.0 附带一个稳定的规范、一个功能丰富且快速的参考实现DuckDBducklake扩展以及未来发展的路线图。DuckLake 概览如果你是新来的可能会想知道DuckLake 是什么DuckLake 是一种湖仓一体格式允许你将数据存储在对象存储上并像访问数据库一样访问它类似于带有 Unity Catalog 的 Delta Lake 和带有 Lakekeeper 的 Iceberg。其他格式与 DuckLake 的一个关键区别在于DuckLake 将所有元数据存储在一个数据库中这通常被称为目录。这个数据库可以是任何支持 SQL、支持主键并且能够将数据持久化到表中的系统。DuckLake 规范定义了特定版本所需的元数据表、支持的数据类型以及关于如何检索表元数据以在湖仓一体上执行操作的参考。我们还使用 DuckDB 作为引擎开发了该规范的一个实现即 DuckDBducklake扩展。该扩展实现了整个规范并支持三种主要的目录SQLite、PostgreSQL 和 DuckDB是的DuckDB 也可以作为目录。在过去的一年里我们持续与社区一起在内部推进 DuckLake 规范的工作。我们支持了在不创建深度副本的情况下添加现有的 Parquet 文件引入了与 Iceberg 的兼容性并推出了对GEOMETRY和VARIANT类型的支持。我们还发布了几份从 DuckDB 到 DuckLake 的迁移指南和脚本。DuckLake 解锁了几个有趣的用例。使用数据内联功能利用目录数据库来暂存小规模更新允许你将数据流式传输到数据湖中。利用其轻量级的设置你只需要一些存储空间和一个公共的 HTTPS 端点就可以提供一个无需身份验证的只读湖仓一体。在 DuckDB 的背景下它还解锁了多人协作的设置其中多个 DuckDB 实例可以访问同一个 DuckLake同时通过一个中心的 PostgreSQL 目录数据库进行协调。采用情况我们很高兴看到社区如此迅速地采用了 DuckLake。根据下载统计ducklakeDuckDB 扩展目前已位列 DuckDB 核心扩展的前十名。现在已有适用于 Apache DataFusion由 Hotdata 提供、Apache Spark由 MotherDuck 和 Andrew Witten 提供、Trino 以及 Pandas dataframe主要通过代理编码生成的 DuckLake 客户端。MotherDuck 还提供了一个托管的 DuckLake 服务他们为你同时管理目录数据库和数据存储。我们非常自豪的是DuckLake 已经在数十家公司的生产环境中得到使用——请参阅我们新落地页上的标志集合。甚至还有一本 O’Reilly 的 DuckLake 书籍正在编写中《DuckLake权威指南》书籍封面有关更多 DuckLake 的用例和库请参阅 awesome-ducklake 仓库。DuckLake v1.0 的新特性首先也是最重要的DuckLake 包含了数十个错误修复使该格式在生产部署中更加健壮参见附录。我们特别高兴的是许多贡献是由社区成员做出的我们要感谢他们的工作下面我们展示 DuckLake v1.0 的一些关键特性——这些特性在今日同步发布的 DuckDB v1.5.2 中可用。数据内联数据内联是 DuckLake 的旗舰特性之一。它基本上支持在目录数据库中进行小型插入、删除和更新操作避免了“小文件问题”的扩散。DuckLake v1.0 带来了完整的更新和删除内联功能。此特性现在默认开启默认阈值为 10 行。如果你想了解更多关于此特性的信息请前往我们最近发布的这篇博客。在这个例子中我们执行了插入、删除和更新操作并展示了这如何不会在 DuckLake 中创建任何新文件。然后我们执行CHECKPOINT将内联数据刷新到对象存储。CREATETABLElake.t(idINT,statusVARCHAR);INSERTINTOlake.tVALUES(1,en route),(2,shipped);DELETEFROMlake.tWHEREid1;UPDATElake.tSETstatusdeliveredWHEREid2;FROMducklake_list_files(lake,t);-- 返回空CHECKPOINT;-- 刷新数据排序表如果你经常对高基数列如 id 或时间戳运行查询排序是提高读取查询性能的好方法。对于在排序列键上推送过滤器的查询行组和文件裁剪都将受益。排序表支持列排序也支持任意 SQL 表达式。默认方法会在压缩、刷新或插入时对表进行排序但可以禁用后一种方式以避免影响写入性能。CREATETABLElake.sorted_t(idINT,payload JSON);ALTERTABLElake.sorted_tSETSORTEDBY(idASC);INSERTINTOlake.sorted_tVALUES(33,{key:value}),(2,{key:value}),(42,{key:value}),(1,{key:value});CHECKPOINT;FROMlake.sorted_t;桶分区分桶的工作原理是对目标列的值进行哈希计算然后根据桶的数量取模将该值分配到一个特定的桶中。桶分区功能使用murmur3哈希实现以保证与 Iceberg 完全兼容。如果你想获得分区的一些好处但你的列具有高基数分桶是一个很好的替代方案。CALLlake.set_option(data_inlining_row_limit,0);CREATETABLElake.events(user_nameVARCHAR,event_typeVARCHAR,tsTIMESTAMP);ALTERTABLElake.eventsSETPARTITIONEDBY(bucket(8,user_name));INSERTINTOlake.eventsVALUES(alice,click,2024-01-01),(bob,view,2024-01-01),(charlie,click,2024-01-02);EXPLAINANALYZEFROMlake.eventsWHEREuser_namealice;类型系统Geometry继GEOMETRY数据类型被添加到 DuckDB 核心之后我们启用了更好的地理统计信息以实现过滤器下推。GEOMETRY类型现在也可以嵌套在结构体、列表和映射中。在下面的例子中我们演示了如何使用运算符实现一个简单的过滤器下推该运算符检查两个几何图形的边界框是否重叠。LOADspatial;CALLlake.set_option(data_inlining_row_limit,0);CREATETABLElake.places(nameVARCHAR,locationGEOMETRY);INSERTINTOlake.placesVALUES(Amsterdam,ST_Point(4.9,52.37));INSERTINTOlake.placesVALUES(London,ST_Point(-0.12,51.51));SELECTnameFROMlake.placesWHERElocationST_GeomFromText(POLYGON((4 52, 5 52, 5 53, 4 53, 4 52)));类型系统VariantVARIANT是一种与 JSON 类似的类型但具有一些非常独特的特性使其成为更优的选择即(i) 它支持比 JSON 多得多的类型例如DATE或TIMESTAMP(ii) 它以二进制编码格式存储而不是字符串(iii) 它可以被拆分shredded为原始类型这带来了更好的查询性能包括过滤器和投影下推。我们相信VARIANT最终将取代 JSON成为数据库系统中处理半结构化数据的主要类型。CREATETABLElake.events(idINT,payload VARIANT);INSERTINTOlake.eventsVALUES(1,{user:alice,ts:TIMESTAMP2024-01-01}),(2,{user:bob,ts:TIMESTAMP2024-01-02,rand:value});SELECT*FROMlake.eventsWHEREpayload.userbob;删除向量删除向量是在 Iceberg v3 规范中引入的。在开发 DuckLake 的同时我们也努力在数据层面保持与 Iceberg 的兼容性。因此我们实现了存储为 Puffin 文件的删除向量。这些删除向量的工作方式与删除文件已经是 Iceberg 规范的一部分类似。此特性是实验性的我们计划在即将发布的 DuckLake 版本中进行一些改进。CREATETABLElake.t(idINTEGER);CALLlake.set_option(write_deletion_vectors,true,table_namet);INSERTINTOlake.tFROMrange(100);DELETEFROMlake.tWHEREid5;DuckLake 的未来尽管今天我们发布了 DuckLake v1.0但工作尚未完成。我们将继续发布新的 DuckLake 规范版本在此我们概述了 DuckLake v1.1 的当前计划以及 DuckLake v2.0 的可能方向。DuckLake v1.1DuckLake v1.1 计划了两个主要特性这需要规范变更Variant 内联。目前Variant 内联仅适用于原生支持它的目录例如DuckDB。但是如果目录不支持VARIANT类型则该表将永远不会被内联。我们将设计和实施必要的规范变更以实现这一点。多删除向量 Puffin 文件。DuckLake v1.0 已经支持单删除向量 Puffin 文件但我们希望确保类似于我们当前的部分删除文件DuckLake 可以在一个文件中存储和读取多个删除向量从而在最大程度减少小文件问题的同时仍然保留时间旅行信息。DuckLake v2.0DuckLake v2.0 很可能不会很快到来因为我们将专注于完善我们当前的功能集并保证规范的稳定性。尽管我们对自己想要解决的问题有一个粗略的概念但社区的需求也将强烈地推动我们的计划因此功能可能会随时间推移而添加或重新调整优先级。以下是我们目前认为对 DuckLake v2.0 很重要的功能列表类似 Git 的分支。允许用户创建其 DuckLake 的分支并在它们之间合并更改。类似于 Git 对代码的作用但这是针对数据的。基于权限的角色。定义角色和权限以控制对 DuckLake 对象和操作的访问。这已经可以通过正确配置 Postgres 和你的 S3 存储桶来实现但我们希望使其更容易通过 DuckLake 直接管理。增量物化视图。支持可以通过应用 DuckLake 表中追踪的更改来增量刷新而不是重新计算整个视图的物化视图。结论今天我们发布了 DuckLake v1.0一个稳定的 DuckLake 规范以及与此规范版本兼容的 DuckDBducklake扩展。我们对 DuckLake 在仅仅一年内取得的进展感到非常高兴它获得了社区的良好采用并为未来的改进奠定了坚实的基础。如果你想从 DuckLake 的开发者那里听到更多信息请务必查看我们关于 DuckLake v1.0 的播客节目。附录这是自设定 1.0 目标以来社区和 DuckDB Labs 团队为 DuckLake 所做的所有工作。在本附录中我们列出了自 2025 年底以来已合并的 108 个 PR。我们对它们进行了分类以传达我们一直专注于使 DuckLake 稳定且可用于生产环境其中合并了 68 个专注于可靠性和正确性的 PR12 个专注于内部重构以为未来发展奠定基础的 PR以及另外 12 个专注于性能改进的 PR。