发布 DuckDB 0.8.0
DuckDB 团队很高兴地宣布发布最新的 DuckDB 版本(0.8.0)。该版本以墨西哥湾特有的斑嘴鸭(Anas Fulvigula)命名为“Fulvigula”。
要安装新版本,请访问安装指南。完整发布说明可在 GitHub 上查阅。
0.8.0 版本新特性
更改内容太多,无法逐一详细讨论,但我们想重点介绍几个特别令人兴奋的特性!
- 新的 PIVOT 和 UNPIVOT 语句
- 并行数据导入/导出改进
- 时间序列连接
- 递归式通配符匹配
- 存储元数据惰性加载,启动时间更快
- Python 用户定义函数
- 支持 Arrow 数据库连接 (ADBC)
- 新的 Swift 集成
以下是这些新功能的总结和示例,首先介绍我们 SQL 方言中的两项重大变更,这些变更旨在默认情况下产生更直观的结果。
破坏性 SQL 更改
此版本包含 SQL 方言中的两项重大变更:除法运算符默认使用浮点除法,并且默认空值排序顺序从 NULLS FIRST
更改为 NULLS LAST
。虽然 DuckDB 仍处于 Beta 阶段,但我们认识到许多 DuckDB 查询已在生产中使用。因此,可以使用以下设置恢复旧行为:
SET integer_division = true;
SET default_null_order = 'NULLS_FIRST';
除法运算符。除法运算符 /
现在即使使用整数参数也将始终执行浮点除法。新运算符 //
保留了旧的语义,可用于执行整数除法。这使得 DuckDB 的除法运算符对初学者来说更不容易出错,并且与 Python 3 以及 Spark、Snowflake 和 BigQuery 等 OLAP 领域其他系统中的除法运算符保持一致。
SELECT 42 / 5, 42 // 5;
(42 / 5) | (42 // 5) |
---|---|
8.4 | 8 |
默认空值排序顺序。默认空值排序顺序从 NULLS FIRST
更改为 NULLS LAST
。此更改的原因是,当与 LIMIT
结合使用时,NULLS LAST
排序顺序更直观。使用 NULLS FIRST
时,Top-N 查询总是首先返回 NULL
值。而使用 NULLS LAST
时,则返回实际的 Top-N 值。
CREATE TABLE bigdata (col INTEGER);
INSERT INTO bigdata VALUES (NULL), (42), (NULL), (43);
FROM bigdata ORDER BY col DESC LIMIT 3;
v0.7.1 | v0.8.0 |
---|---|
NULL | 43 |
NULL | 42 |
43 | NULL |
新 SQL 特性
PIVOT 和 UNPIVOT。数据有各种形状和大小,我们并不总能控制数据的生成过程。虽然 SQL 非常适合重塑数据集,但在原生 SQL 中将列转换为行或将行转换为列是繁琐的。在此版本中,DuckDB 引入了 PIVOT
和 UNPIVOT
语句,允许重塑数据集,使行转换为列或反之。DuckDB 语法的一个关键优势是,要进行 PIVOT 或 UNPIVOT 的列名可以自动推断。这是一个简短的示例:
CREATE TABLE sales (year INTEGER, amount INTEGER);
INSERT INTO sales VALUES (2021, 42), (2022, 100), (2021, 42);
PIVOT sales ON year USING sum(amount);
2021 | 2022 |
---|---|
84 | 100 |
时间序列的 ASOF 连接。当时间序列数据与背景事实表连接时,时间戳通常不完全匹配。在这种情况下,通常需要连接行,使时间戳与最近的时间戳连接。ASOF 连接可用于此目的——它执行模糊连接以查找每行的最接近连接伙伴,而不是要求精确匹配。
CREATE TABLE a (ts TIMESTAMP);
CREATE TABLE b (ts TIMESTAMP);
INSERT INTO a VALUES (TIMESTAMP '2023-05-15 10:31:00'), (TIMESTAMP '2023-05-15 11:31:00');
INSERT INTO b VALUES (TIMESTAMP '2023-05-15 10:30:00'), (TIMESTAMP '2023-05-15 11:30:00');
FROM a ASOF JOIN b ON a.ts >= b.ts;
a.ts | b.ts |
---|---|
2023-05-15 10:31:00 | 2023-05-15 10:30:00 |
2023-05-15 11:31:00 | 2023-05-15 11:30:00 |
请查阅文档了解更深入的解释。
数据集成改进
默认并行 CSV 读取器。在此版本中,并行 CSV 读取器已得到极大改进,现在是默认的 CSV 读取器。我们要感谢所有试用过实验性读取器的用户提供的宝贵反馈和报告。experimental_parallel_csv
标志已被弃用,不再需要。并行 CSV 读取器能够更高效地读取大型 CSV 文件。
CREATE TABLE lineitem AS FROM lineitem.csv;
v0.7.1 | v0.8.0 |
---|---|
4.1 秒 | 1.2 秒 |
并行Parquet、CSV 和 JSON 写入。此版本支持并行且保持顺序的 Parquet、CSV 和 JSON 文件写入。因此,默认情况下,写入这些文件格式是并行的,并且无需禁用插入顺序保留,写入这些格式的速度也大大加快。
COPY lineitem TO 'lineitem.csv';
COPY lineitem TO 'lineitem.parquet';
COPY lineitem TO 'lineitem.json';
格式 | v0.7.1 | v0.8.0 |
---|---|---|
CSV | 3.9 秒 | 0.6 秒 |
Parquet | 8.1 秒 | 1.2 秒 |
JSON | 4.4 秒 | 1.1 秒 |
使用 **
进行递归文件通配符匹配。此版本增加了对递归通配符匹配的支持,可以使用 **
运算符(双星号)匹配任意数量的子目录。
FROM 'data/glob/crawl/stackoverflow/**/*.csv';
文档已更新,包含此语法的各种示例。
存储改进
表元数据惰性加载。DuckDB 的内部存储格式存储表中每个行组的元数据,例如最小-最大索引以及每个行组在文件中的存储位置。过去,一旦数据库打开,DuckDB 就会立即加载此元数据。然而,一旦数据变得非常大,元数据也会变得相当大,导致数据库启动时出现明显的延迟。在此版本中,我们优化了 DuckDB 的元数据处理,仅在访问时才读取表元数据。因此,即使对于大型数据库,启动也几乎是瞬时的,并且仅为查询中实际使用的列加载元数据。下面的基准测试针对包含单个大型 TPC-H lineitem
表(120× SF1)的数据库文件,该表包含约 7.7 亿行和 16 列:
查询 | v0.6.1 | v0.7.1 | v0.8.0 | Parquet |
---|---|---|---|---|
SELECT 42 |
1.60 秒 | 0.31 秒 | 0.02 秒 | - |
FROM lineitem LIMIT 1 |
1.62 秒 | 0.32 秒 | 0.03 秒 | 0.27 秒 |
客户端
Python 用户定义标量函数。现在可以将任意 Python 函数注册为 SQL 查询中的标量函数。这仅在使用 Python 调用 DuckDB 时有效,因为它使用 DuckDB 运行的实际 Python 运行时。虽然可以将普通的 Python 值传递给函数,但也有一个向量化变体,它在底层使用 PyArrow,以实现更高的效率和更好的并行性。
import duckdb
from duckdb.typing import *
from faker import Faker
def random_date():
fake = Faker()
return fake.date_between()
duckdb.create_function('random_date', random_date, [], DATE)
res = duckdb.sql('SELECT random_date()').fetchall()
print(res)
# [(datetime.date(2019, 5, 15),)]
请参阅文档了解更多信息。
支持 Arrow 数据库连接 (ADBC)。ADBC 是一种数据库 API 标准,用于数据库访问库,它使用 Apache Arrow 传输查询结果集和摄取数据。使用 Arrow 对此特别有利,因为它能改善传统上通过模拟基于行的 API(如 JDBC/ODBC)而遭受性能损失的列式数据管理系统。从本版本开始,DuckDB 原生支持 ADBC。我们很高兴成为首批提供原生支持的系统之一,并且 DuckDB 的进程内设计与 ADBC 非常契合。
Swift 集成。DuckDB 获得了另一个官方语言集成:Swift。Swift 是 Apple 开发的一种语言,最显著的用途是为 Apple 设备创建应用程序,但它也越来越多地用于服务器端开发。DuckDB Swift API 允许所有 Swift 平台上的开发人员使用原生 Swift 接口来利用 DuckDB,并支持 Swift 的强类型和并发等特性。
结语
完整发布说明可在GitHub 上查阅。我们要感谢所有贡献者为改进 DuckDB 所付出的辛勤工作。