DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性

发布时间:2026/6/1 22:22:14

DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性 来源https://duckdb.org/2026/05/29/new-iceberg-features.htmlDuckDB-Iceberg 在 v1.5.3 中的新特性作者:Tom Ebergen, Thijs Bruineman日期:2026-05-29阅读时间:5 分钟摘要:DuckDB-Iceberg 现在拥有许多新特性来支持 Iceberg 表和 Iceberg REST Catalog包括MERGE INTO、ALTER TABLE、分区转换partition transforms、V3 支持等尽管开发 DuckLake v1.0 和 Quack 所需的功能需要大量工作DuckLabs 团队仍在努力开发 DuckDB-Iceberg 扩展。在这篇博文中我们将演示 DuckDB v1.5.3 中可用的一些功能。其中许多功能在我们上一篇以 Iceberg 为主题的博文“DuckDB-Iceberg 中的写入操作”中被指定为未来版本发布的功能——你可以将本文视为那篇博文的“第 2 部分”。入门指南要体验新的 DuckDB-Iceberg 功能你需要连接到常用的 Iceberg REST Catalog。有很多方法可以做到这一点请查看“连接到 REST Catalog”页面其中包含连接到 Apache Polaris 和 Lakekeeper 等 catalog 的说明。如果你想连接到 Amazon S3 Tables请查阅“连接到 S3 Tables”页面。无论如何你的ATTACH命令看起来会像这样ATTACHwarehouse_nameASmy_datalake(TYPEiceberg,other options);MERGE INTO 支持当目标表没有主键时所有数据湖仓格式都是这种情况DuckDB 的MERGE INTO语句是表达 upsert 操作的推荐方式。从 v1.5.3 开始MERGE INTO现已完全支持 Iceberg 表。你可以在一条语句中对 Iceberg 表应用一个变更集按行决定是插入、更新还是删除。我们以这张表为例CREATETABLEmy_datalake.default.people(idINTEGER,nameVARCHAR,salaryFLOAT);INSERTINTOmy_datalake.default.peopleVALUES(1,John,92_000.0),(2,Anna,100_000.0);┌───────┬─────────┬──────────┐ │ id │ name │ salary │ │ int32 │varchar│float│ ├───────┼─────────┼──────────┤ │1│ John │92000.0│ │2│ Anna │100000.0│ └───────┴─────────┴──────────┘让我们对该表运行一次更新包含两条记录一条增加 ID 为 1 的人的薪水另一条添加一个 ID 为 3 的新人。MERGEINTOmy_datalake.default.peopleAStargetUSING(FROM(VALUES(1,John,105_000.0),(3,Sarah,95_000.0))t(id,name,salary))ASupsertsON(upserts.idtarget.id)WHENMATCHEDTHENUPDATEWHENNOTMATCHEDTHENINSERT;查询结果时我们得到以下结果SELECT*FROMmy_datalake.default.peopleORDERBYid;┌───────┬─────────┬──────────┐ │ id │ name │ salary │ │ int32 │varchar│float│ ├───────┼─────────┼──────────┤ │1│ John │105000.0│ │2│ Anna │100000.0│ │3│ Sarah │95000.0│ └───────┴─────────┴──────────┘你也可以将匹配MATCHED和不匹配NOT MATCHED分支与WHEN MATCHED THEN DELETE组合起来在同一个语句中表达一个删除集。与UPDATE和DELETE一样MERGE INTO使用读时合并merge-on-read语义并将位置删除positional deletes写入 Iceberg 表。ALTER TABLE 支持在 DuckDB v1.4 的 Iceberg 扩展中Iceberg 表缺乏模式演化schema evolution是一个已知的限制。在 v1.5.3 中ALTER TABLE语句现已支持 Iceberg 表涵盖了最常见的模式演化操作。-- 创建表CREATETABLEmy_datalake.default.simple_tableASFROM(VALUES(1,Andy),(2,Bob),(3,Claire),(4,Mr. Duck))t(col1,col2);-- 重命名表ALTERTABLEmy_datalake.default.simple_tableRENAMETOrenamed_table;-- 添加列ALTERTABLEmy_datalake.default.renamed_tableADDCOLUMNcol3DOUBLE;-- 重命名列ALTERTABLEmy_datalake.default.renamed_tableRENAMECOLUMNcol2TOname;-- 删除列ALTERTABLEmy_datalake.default.renamed_tableDROPCOLUMNcol3;-- 设置格式版本ALTERTABLEmy_datalake.default.renamed_tableSET(format-version3);在模式更改后查询该表我们得到以下结果SELECT*FROMmy_datalake.default.renamed_tableORDERBYcol1;┌───────┬──────────┐ │ col1 │ name │ │ int32 │varchar│ ├───────┼──────────┤ │1│ Andy │ │2│ Bob │ │3│ Claire │ │4│ Mr.Duck │ └───────┴──────────┘在后台每个ALTER TABLE语句都会更新 Iceberg 表的current-schema-id。这些更改在其他能够识别 Iceberg 的引擎下次查询LoadTableInformation端点时就会变得可见。Iceberg 模式演化仅涉及元数据因此不会重写任何数据文件。truncate 和 bucket 支持Iceberg 规范定义了多种分区转换partition transforms用于确定数据文件在磁盘上的布局方式。在 v1.5.3 中DuckDB-Iceberg 支持创建、插入和更新使用bucket和truncate分区转换的表。bucket(N, col)转换将列的值哈希到 N 个桶中这在你想对高基数列进行稳定分区时非常有用。truncate(W, col)按前 W 个字符对行进行分组对于数值列则按向下舍入到 W 的倍数进行分组这对于基于前缀的分区非常有用。CREATETABLEmy_datalake.default.events(event_idBIGINT,user_idBIGINT,countryVARCHAR,payloadVARCHAR)PARTITIONEDBY(bucket(16,user_id),truncate(2,country));INSERTINTOmy_datalake.default.eventsVALUES(1,1001,United States,click),(2,1002,United Kingdom,view),(3,1003,Germany,click),(4,1004,Netherlands,view);你可以检查生成的数据文件以验证分区SELECTfile_path,record_countFROMiceberg_metadata(my_datalake.default.events)WHEREcontentEXISTING;针对使用bucket和truncate分区的表的更新和删除操作也得到支持在读时合并语义下使用位置删除。Iceberg 模式属性Iceberg catalog 允许在模式namespace级别附加任意的键值属性。这些属性通常用于记录所有权、描述、默认存储位置或任何适用于模式中每个表的其他元数据。iceberg_schema_propertiesset_iceberg_schema_propertiesremove_iceberg_schema_properties你可以如下使用它们-- 设置模式属性CALLset_iceberg_schema_properties(my_datalake.default,{owner:analytics-team,description:Default analytics schema});-- 读取模式属性SELECT*FROMiceberg_schema_properties(my_datalake.default);┌─────────────┬──────────────────────────┐ │key│value│ │varchar│varchar│ ├─────────────┼──────────────────────────┤ │ owner │ analytics-team │ │ description │Defaultanalyticsschema│ └─────────────┴──────────────────────────┘-- 删除模式属性CALLremove_iceberg_schema_properties(my_datalake.default,[description]);模式属性通过 Iceberg REST Catalog 写入因此任何连接到同一 catalog 的其他能够识别 Iceberg 的引擎都会立即看到更新。返回的值是剩余模式属性的数量。V3 支持Iceberg v3 规范引入了几个新特性DuckDB-Iceberg 现在对这些特性同时支持读取和写入VARIANT和TIMESTAMP_NS数据类型列的模式级默认值二进制删除向量行血缘追踪实际中最大的变化是二进制删除向量。在 v2 表中DuckDB-Iceberg 将位置删除写入 Parquet 文件在 v3 表中相同的信息被编码为更紧凑的二进制删除向量Puffin 文件。DuckDB 会根据表的format-version自动选择正确的格式。你可以通过在创建表时设置format-version表属性来创建一个 v3 表CREATETABLEmy_datalake.default.v3_tableWITH(format-version3)ASFROM(VALUES(1,{kind:click,x:10}::VARIANT,TIMESTAMP_NS2026-05-20 12:00:00.123456789),(2,{kind:view}::VARIANT,TIMESTAMP_NS2026-05-20 12:00:00.987654321))t(id,payload,event_time);-- 针对 v3 表的删除操作会写入二进制删除向量DELETEFROMmy_datalake.default.v3_tableWHEREid1;SELECT*FROMmy_datalake.default.v3_table;┌───────┬──────────────────┬───────────────────────────────┐ │ id │ payload │ event_time │ │ int32 │ variant │ timestamp_ns │ ├───────┼──────────────────┼───────────────────────────────┤ │2│ {kind:view} │2026-05-2012:00:00.987654321│ └───────┴──────────────────┴───────────────────────────────┘查看表的元数据可以确认删除操作是作为删除向量而不是位置删除 Parquet 文件写入的SELECTmanifest_content,content,file_formatFROMiceberg_metadata(my_datalake.default.v3_table);┌──────────────────┬──────────────────┬─────────────┐ │ manifest_content │ content │ file_format │ │varchar│varchar│varchar│ ├──────────────────┼──────────────────┼─────────────┤ │DATA│ EXISTING │ parquet │ │DELETE│ POSITION_DELETES │ puffin │ └──────────────────┴──────────────────┴─────────────┘注意DuckDB-Iceberg 目前还不支持 Geography 类型和 Unknown 类型我们计划在 DuckDB v2.0.0 中添加它们。结论与未来工作通过这些功能DuckDB-Iceberg 已经填补了上一篇博文中提到的许多空白分区写入、模式演化、MERGE INTO以及许多 Iceberg v3 功能现已可用。未来还有更多功能将要实现一如既往如果您希望某个特定功能得到优先处理请通过 DuckDB-Iceberg GitHub 仓库与我们联系或直接与我们的工程师沟通。

相关新闻