发布 DuckDB 1.2.0
简而言之:DuckDB 团队很高兴地宣布,我们今天发布了 DuckDB 1.2.0 版本,代号为“Histrionicus”。
要安装新版本,请访问安装指南。有关发布说明,请参阅发布页面。
由于发布流程中需要审核,一些软件包(Go、R、Java)的发布可能需要额外几天时间。
我们很荣幸发布 DuckDB 1.2.0。此版本代号为“Histrionicus”,取自外形优美的斑脸海番鸭 (Histrionicus histrionicus),它们栖息在“北美、格陵兰岛、冰岛和俄罗斯东部寒冷湍急的溪流中”。
1.2.0 版本新特性
改动内容太多,无法一一详细讨论,但我们想重点介绍一些特别重要和令人兴奋的特性!下面是这些新特性及其示例的总结。
不兼容的更改
random
函数现在使用更大的状态。 这意味着它现在更随机™。由于此更改,固定的种子现在将生成与 DuckDB 以前版本不同的值。
map['entry']
现在返回一个值,而不是一个条目列表。 例如,map(['k'], ['v'])['k']
现在返回 'v'
,而以前返回 ['v']
。我们还引入了 map_extract_value
函数,它现在是方括号运算符 []
的别名。如果您想返回一个列表,请使用map_extract
函数:map_extract(map(['k'], ['v']), 'k') = ['v']
。
list_reduce
的索引已修复。 当索引应用于 list_reduce
时,索引指向 lambda 函数的最后一个参数,并且索引从 1 开始。因此,list_reduce(['a', 'b'], (x, y, i) -> x || y || i)
返回 ab2
。
显式存储版本
DuckDB v1.2.0 包含了新的压缩方法,但默认尚未启用,以确保旧版本的 DuckDB 能够读取由 DuckDB v1.2.0 生成的文件。
实际上,这意味着 DuckDB v1.2.0 可以读取由过去的稳定 DuckDB 版本(如 v1.0.0)写入的数据库文件。在使用默认设置的 DuckDB v1.2.0 时,旧版本可以读取由 DuckDB v1.2.0 写入的文件。
您可以使用以下语法选择启用新的向前不兼容特性
ATTACH 'file.db' (STORAGE_VERSION 'v1.2.0');
此设置指定了能够读取数据库文件的最小 DuckDB 版本。当数据库文件使用此选项写入时,生成的文件无法被早于指定版本的 DuckDB 发布版本打开。它们可以被指定版本和所有更新的 DuckDB 版本读取。
如果您连接到 DuckDB 数据库,可以使用以下命令查询存储版本
SELECT database_name, tags FROM duckdb_databases();
这显示了存储版本
┌───────────────┬───────────────────────────────────┐
│ database_name │ tags │
│ varchar │ map(varchar, varchar) │
├───────────────┼───────────────────────────────────┤
│ file1 │ {storage_version=v1.2.0} │
│ file2 │ {storage_version=v1.0.0 - v1.1.3} │
│ ... │ ... │
└───────────────┴───────────────────────────────────┘
这意味着 file2
可以被过去的 DuckDB 版本打开,而 file1
仅与 v1.2.0
(或未来版本)兼容。
要在 DuckDB v1.2.0 中将新格式转换为旧格式以实现兼容性,请使用以下序列
ATTACH 'file1.db';
ATTACH 'converted_file.db' (STORAGE_VERSION 'v1.0.0');
COPY FROM DATABASE file1 TO converted_file;
索引
ALTER TABLE ... ADD PRIMARY KEY
。 经过很长一段时间,DuckDB 终于能够为现有表添加主键了 🎉。因此,现在可以运行此操作
CREATE TABLE tbl (id INTEGER);
INSERT INTO tbl VALUES (42);
ALTER TABLE tbl ADD PRIMARY KEY (id);
解决了过度活跃的约束检查问题。 我们还解决了过度活跃的唯一约束检查这一长期存在的问题。例如,以下命令序列过去会抛出错误,但现在可以正常工作了
CREATE TABLE students (id INTEGER PRIMARY KEY, name VARCHAR);
INSERT INTO students VALUES (1, 'John Doe');
BEGIN; -- start transaction
DELETE FROM students WHERE id = 1;
INSERT INTO students VALUES (1, 'Jane Doe');
CSV 特性
Latin-1 和 UTF-16 编码。 以前,DuckDB 的 CSV 读取器仅限于 UTF-8 文件。它现在可以读取 Latin-1 和 UTF-16 文件。例如
FROM read_csv('cities-latin-1.csv', encoding = 'latin-1');
多字节分隔符。 DuckDB 现在支持最长 4 字节的分隔符。这意味着您终于可以将鸭子表情符号用作列分隔符了。例如
a🦆b
hello🦆world
FROM read_csv('example.dsv', sep = '🦆');
严格 CSV 解析。 RFC 4180 规范定义了良好格式的 CSV 文件的要求,例如,具有单一的行分隔符。默认情况下,DuckDB 现在以所谓的严格模式(`strict_mode = true`)解析 CSV。例如,以下 CSV 文件由于混合了换行符而被拒绝
echo "a,b\r\nhello,42\nworld,84" > rfc_4180-defiant.csv
FROM read_csv('rfc_4180-defiant.csv');
Invalid Input Error:
Error when sniffing file "rfc_4180-defiant.csv".
It was not possible to automatically detect the CSV Parsing dialect/types
但它可以与更宽松的选项 strict_mode = false
一起解析
FROM read_csv('rfc_4180-defiant.csv', strict_mode = false);
┌─────────┬───────┐
│ a │ b │
│ varchar │ int64 │
├─────────┼───────┤
│ hello │ 42 │
│ world │ 84 │
└─────────┴───────┘
性能改进。 新版本中的 CSV 解析器使用了一种新的算法在并行执行时查找新行。这使得速度提高了约 15%。
无限行长度。 以前,DuckDB 的 CSV 文件行长限制为 8 MB。新版本取消了这一限制,行长可以任意长。
Parquet 特性
Parquet 字典和布隆过滤器支持。 DuckDB 现在支持使用字典编码写入更多类型。这在某些情况下可以减小文件大小。DuckDB 现在还能够读取和写入 Parquet 布隆过滤器。布隆过滤器是小型索引数据结构,如果设置了过滤器,可用于排除行组。这对于经常重复但无序的数据(例如,分类值)特别有用。后续将发布一篇单独的博客文章。
Parquet 的 Delta 二进制打包压缩。 DuckDB 现在支持 DELTA_BINARY_PACKED
压缩以及 Parquet 文件的 DELTA_LENGTH_BYTE_ARRAY
和 BYTE_STREAM_SPLIT
选项。几周前,我们在一篇博客文章中详细阐述了这些内容。
CLI 改进
安全模式。 DuckDB 命令行客户端现在支持安全模式,可以通过 -safe
标志或 .safe_mode
点命令激活。在此模式下,CLI 客户端被阻止访问除其最初连接的数据库文件之外的外部文件,并被阻止与主机文件系统交互。有关更多信息,请参阅操作手册中的“保护 DuckDB”页面。
更好的自动补全。 CLI 中的自动补全现在使用解析表达式文法 (PEG) 以提供更好的自动补全,以及改进的错误消息和建议。
美观地打印大数字。 如果客户端只渲染单行,CLI 会提供打印数字的摘要。
SELECT 100_000_000 AS x, pi() * 1e9 AS y;
┌──────────────────┬───────────────────┐
│ x │ y │
│ int32 │ double │
├──────────────────┼───────────────────┤
│ 100000000 │ 3141592653.589793 │
│ (100.00 million) │ (3.14 billion) │
└──────────────────┴───────────────────┘
友好的 SQL
前缀别名。 SQL 表达式和表别名现在可以指定在它们所指代的事物之前(而不是使用众所周知的 AS
语法)。这在某些情况下可以提高可读性,例如
SELECT
e1: some_long_and_winding_expression,
e2: t2.a_column_name
FROM
t1: long_schema.some_long_table_name,
t2: short_s.tbl;
此想法归功于Michael Toy。一篇单独的博客文章将很快发布。更新:关于前缀别名的博客文章已发布。
RENAME
子句。 DuckDB 现在支持在 SELECT
中使用 RENAME
子句。这允许重命名由*
表达式发出的字段
CREATE TABLE integers (col1 INTEGER, col2 INTEGER);
INSERT INTO integers VALUES (42, 84);
SELECT * RENAME (col1 AS new_col1) FROM integers;
星号 LIKE
。 LIKE
和 SIMILAR TO
子句现在可以用于 *
表达式,作为 COLUMNS
语法的简写。
CREATE TABLE key_val (key VARCHAR, val1 INTEGER, val2 INTEGER);
INSERT INTO key_val VALUES ('v', 42, 84);
SELECT * LIKE 'val%' FROM key_val;
┌───────┬───────┐
│ val1 │ val2 │
│ int32 │ int32 │
├───────┼───────┤
│ 42 │ 84 │
└───────┴───────┘
优化
我们花费了大量时间在 DuckDB 的优化器上。优化器的改进难以量化,但由于这些优化,例如,在 MacBook Pro 上运行 TPC-H SF100 查询时,DuckDB 的总运行时间比以前的版本提高了 13%。
扩展的 C API
目前,DuckDB 扩展使用 DuckDB 的内部 C++ 结构。这——加上一些有趣的链接问题——要求扩展与主线 DuckDB 同步开发并不断更新。从这个版本开始,我们在 duckdb_extension.h
中公开了一个新的 C 风格扩展 API。此 API 可用于在 DuckDB 中创建标量、聚合或表函数。使用此 API 有两个主要优点:首先,许多编程语言(例如 Go、Rust 甚至 Java)都直接绑定到 C API,使得集成相当容易。其次,C 扩展 API 是稳定的且向后兼容的,这意味着针对此 API 的扩展将继续适用于新的 DuckDB 版本。我们将跟进提供一个新的扩展模板。
musl 扩展
为 musl 分发扩展。 musl
C 库常用于轻量级设置,例如运行 Alpine Linux 的 Docker 环境。从这个版本开始,我们正式支持 musl,并为 linux_amd64_musl
平台分发扩展(但尚未支持 linux_arm64_musl
)。请注意,DuckDB 二进制文件(例如 CLI 客户端)尚未针对 musl 平台分发,因此您必须从源代码构建它们。
结语
以上只是一部分亮点——此版本还有更多特性和改进。自 1.1.3 版本发布以来,已有超过 70 位贡献者提交了超过 5,000 次提交。完整(非常长)的发布说明可以在 GitHub 上找到。
我们再次感谢我们出色的社区使用 DuckDB,在 DuckDB 上构建酷炫项目,并通过向我们提供反馈来改进 DuckDB。您的贡献意义重大!