Ohhnews

分类导航

$ cd ..
foojay原文

DuckDB 2.0 正式发布:迄今最大版本,新增服务器模式与异步 I/O

#duckdb#数据库#长期支持#服务器模式#异步i/o

DuckDB 2.0.0 已于 2026 年 10 月 21 日发布,代号“Cinnamon Teal”。团队称这是迄今为止规模最大的功能版本,自 1.5 以来包含近 20,000 次提交。这是一个长期支持(LTS)版本,至少支持到 2027 年 10 月。

如果你此前没有使用过 DuckDB,它是一个进程内分析型数据库,有点像 SQLite,但专为列式分析而构建。它以自有格式存储数据,可直接读取 Parquet、CSV 和 JSON,查询位于 PostgreSQL、MySQL 和 SQLite 中的表,并支持 Iceberg 和 Delta 等数据湖格式,无论数据位于本地磁盘还是对象存储中。默认情况下,它运行在应用程序内部,而不是作为独立服务器运行;不过 2.0 现在也允许你将其作为服务器运行,具体如下文所述。

2.0 有哪些新特性

  • DuckDB 作为服务器。 Quack 线协议现已可用于生产环境,新增的 CONNECT 语句可通过一条命令附加到远程数据库并切换过去。远程下推优化器会将工作下推到 PostgreSQL 和 MySQL,而 -serve 和 -connect 标志可直接从 CLI 启动服务器或加入服务器。
  • 异步 I/O。 Parquet、CSV 和原生存储现在可异步读取,这在面向 s3:// 等对象存储时收益最大。
  • VARIANT 成为一等类型。 这种用于嵌套、灵活数据的类型在 1.5 中引入,现在获得了“shredded”执行能力、一系列 variant_* 函数,以及对 Parquet 读写的支持。
  • 新的 PEG 解析器,现已成为默认解析器。 它取代了从 PostgreSQL 继承而来的旧 YACC/Bison 解析器,可提供精确的错误位置,并允许扩展接入语法。如果遇到问题,可通过 SET enable_legacy_parser = true 回退。
  • 更多 SQL。 CREATE TRIGGER、可修改数据的 CTE、NEAREST 连接、嵌套 schema、JSON 修改函数以及 FETCH FIRST 均在此版本中到来。

CLI 还新增了代理模式,可检测编码代理并输出紧凑的 Markdown 和 JSON 错误信息。

在 Java 中使用 DuckDB

DuckDB 提供了 JDBC 驱动,因此在 Java 中只需添加一个依赖,就能像使用任何其他数据库一样查询它。无需运行服务器。

使用 Maven 时,将以下内容添加到 pom.xml:

$ xml
<dependency>
    <groupId>org.duckdb</groupId>
    <artifactId>duckdb_jdbc</artifactId>
    <version>2.0.0.0</version>
</dependency>

使用 Gradle 时,将以下内容添加到 build.gradle:

$ groovy
implementation 'org.duckdb:duckdb_jdbc:2.0.0.0'

然后连接并查询:

$ java
import java.sql.*;

try (Connection conn = DriverManager.getConnection("jdbc:duckdb:");
     Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery(
         "SELECT count(*) FROM read_parquet('data/*.parquet')")) {
    rs.next();
    System.out.println(rs.getLong(1) + " rows");
}

空的 JDBC URL 会提供一个内存数据库。若要持久化,请将其指向一个文件。借助 2.0 中的异步 Parquet 和 CSV 读取器,对 S3 上数据的查询比早期版本运行得更快。

在格式之间转换

在 Java 中,最方便的操作之一就是将文件从一种格式转换为另一种格式。DuckDB 使用 read_csv、read_json 或 read_parquet 读取输入,并通过 COPY 语句写入输出,因此一次转换只需一条 SQL 语句,中间无需逐行编写 Java 代码。

$ java
import java.sql.*;

try (Connection conn = DriverManager.getConnection("jdbc:duckdb:");
     Statement stmt = conn.createStatement()) {

    // CSV to Parquet
    stmt.execute("COPY (SELECT * FROM read_csv('people.csv')) "
            + "TO 'people.parquet' (FORMAT parquet)");

    // Parquet to JSON
    stmt.execute("COPY (SELECT * FROM read_parquet('people.parquet')) "
            + "TO 'people.json' (FORMAT json)");

    // JSON to CSV
    stmt.execute("COPY (SELECT * FROM read_json('people.json')) "
            + "TO 'people.csv' (FORMAT csv, HEADER)");
}

因为每种格式都经过相同的读取器和写入器,所以任意两种格式之间的转换都以相同方式工作。列名和类型会自动传递,文件可以位于本地磁盘,也可以位于 s3:// 等对象存储中。

升级

2.0 可以读写较旧的数据库文件,且这些文件仍与旧版本兼容。不过,使用 2.0 默认存储写入的文件无法被更早的版本打开,因此请规划好这一步,或设置 storage_compatibility_version,以写入旧版本仍可读取的文件。构建现在需要 C++17 编译器。

DuckDB 团队建议先在影子系统中进行测试,对于关键工作负载,等待第一个补丁版本发布。

DuckDB 迁移指南详细介绍了每一项破坏性变更。

DuckDB 2.0 公告涵盖了其他所有新增内容。