DuckDB 悄悄发布 v1.2.0
DuckDB 团队很高兴地宣布,今天我们发布 DuckDB 版本 1.2.0,代号为“Histrionicus”。这种鸭子栖息在“北美、格陵兰、冰岛和俄罗斯东部寒冷湍急的溪流中”。
1.2.0 中的新功能、变化实在太多,无法一一详细讨论,但我们想重点介绍几个特别重要且令人兴奋的功能!下面是这些新功能的摘要和示例。
重大变化(请关注兼容性)
random函数现在更加随机。
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 文件格式详解: 《数据库筑基课 - 列存之 Parquet》
v1.2.0 支持Parquet 字典和 Bloom 过滤器。DuckDB 现在支持使用字典编码编写更多类型。在某些情况下,这应该会减少parquet文件大小。DuckDB 现在还能够读取和写入 Parquet Bloom 过滤器。Bloom 过滤器是小型索引数据结构,可用于在设置过滤器的情况下排除行组。这对于经常重复但无序的数据(例如分类值)特别有用。
Parquet 的增量二进制压缩。DuckDB 现在支持DELTA_BINARY_PACKED压缩以及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;
RENAME子句。DuckDB 现在支持RENAME中的子句。这允许重命名*表达式发出的SELECT字段:
CREATE TABLE integers(col1 INT, col2 INT);
INSERT INTO integers VALUES (42, 84);
SELECT * RENAME (col1 AS new_col1) FROM integers;
* LIKE子句。SIMILAR TO和LIKE都可以作为COLUMNS列名过滤来使用。
CREATE TABLE key_val(key VARCHAR, val1 INT, val2 INT);
INSERT INTO key_val VALUES ('v', 42, 84);
SELECT * LIKE 'val%' FROM key_val;
┌───────┬───────┐
│ val1 │ val2 │
│ int32 │ int32 │
├───────┼───────┤
│ 42 │ 84 │
└───────┴───────┘
优化
我们在DuckDB 的优化器上投入了 大量 时间 。很难量化优化器的改进,但这些优化的结果是,与上一版本相比,DuckDB在MacBook Pro 上运行 TPC-H SF100 查询的总运行时间提高了 13%。
扩展的 C API
目前,DuckDB 扩展使用 DuckDB 的内部 C++ 结构。这(以及一些有趣的链接问题)需要与主线 DuckDB 同步开发扩展并不断更新。从此版本开始,我们在 中为扩展公开了一个新 C 样式 API duckdb_extension.h。此 API 可用于在 DuckDB 中创建标量、聚合或表函数。使用此 API 有两个主要优点:首先,许多编程语言(例如 Go、Rust 甚至 Java)都直接绑定到 C API,因此集成起来相当容易。其次,C 扩展 API 稳定且向后兼容,这意味着针对此 API 的扩展将继续适用于新版本的 DuckDB。我们将跟进一个新的扩展模板。
musl 扩展
分发 musl 扩展。C 库通常用于轻量级设置,例如运行 Alpine Linux 的 Docker 设置。从此版本开始,我们正式支持 musl 并为该平台分发扩展(但尚未为 分发musl)。linux_amd64_musllinux_arm64_musl
最后的想法
以上只是几个亮点,但此版本中还有更多功能和改进。自我们发布 1.1.3 以来,已有 70 多位贡献者提交了超过 5,000 次提交。完整版(非常长)的发布说明可在 GitHub 上找到。
我们再次感谢我们出色的社区使用 DuckDB、在 DuckDB 上构建出色的项目并通过向我们提供反馈来改进 DuckDB。您的贡献真的意义重大!
目前DuckDB在github已获得超26k star.