DuckDB - An OLAP Database System

Notes: t.cn 是新浪的短链接,点击可能会有跳转提示。

DuckDB is an in-process SQL OLAP database management system。就像 SQLite 几乎每个现代的手机都会用到一样,DuckDB 可能真会成为分析领域的 SQLite: http://t.cn/A6oaFFR9 。2019 年 SIGMOD 有一篇 Demo 论文介绍 DuckDB:an embedded analytical database。随着单机内存的变大,大部分 OLTP 数据库都能在内存中放得下,而很多 OLAP 也有在单机就能搞定的趋势。单台服务器的内存很容易达到 TB,加上 SSD,搞个几十甚至上百 TB 很容易。DuckDB 就是为了填补这个空白而生的。如今,它已经成熟稳定了很多。在它之前其实 CWI 做过好几个比较成功的系统,例如 MonetDB(荷兰人喜欢艺术家莫奈)。它也吸取了 MonetDBLite 等的经验教训。

Query Data

时间来到 2022 年 10 月,DuckDB 相对 2019 年 SIGMOD 介绍的版本而言发生了很大的变化。它已经支持 R、Python、Node.js、C++、Java 等众多语言,也有自己的命令行版本。如果用 Python 查询和处理表格类型的数据,它是比 numpy、pandas 等更强大的选择。可以读取的格式包括 Parquet、CSV、SQLite;Pandas、R 和 Julia 的 data frames,当然也包括时髦的 Apache Arrow。现在它甚至支持直接查询 PostgreSQL 的数据,也可以写入它。测试显示直接读 pgsql 有不少查询比 pgsql 本身快很多,不过它还是比先把数据导入 DuckDB,再做的查询要慢不少。http://t.cn/A6oCIEYw 是它的在线demo入口。

DuckDB 既然定位为 OLAP 领域的 SQLite,必须能在读取 Parquet 等文件做查询上超过 pandas 等。从使用接口的角度看,必须要支持标准 SQL 语言,当然也得支持 Python 风格的写法。数据库常用的谓词下推、分区裁剪等都可以发挥作用了,因此 DuckDB 性能吊打 pandas;虽然后者也可以手写代码最优化,但对开发人员的要求就太高了:https://duckdb.org/2021/06/25/querying-parquet.html

Compression

DuckDB 最典型的形态是个库或包,为了方便使用,在 Windows 上还有个命令行版本,甚至还有个 ODBC 驱动。既然它号称是 OLAP 领域的 SQLite,那就必须把命令行搞的跟后者很像:.help 看看,果然如此。 DuckDB 去年(2021)上半年还不支持压缩,经过一年多的迭代,已经取得了长足的进步。虽然它因为采用了定长页面,且页面大小不够大,对通用的压缩算法,如 zstd、snappy、lz4 等不太友好,从而只能用轻量级的压缩算法,如常量、RLE、字典、Bit Packing 等等。其压缩效果已经逐渐逼近通用压缩:https://duckdb.org/2022/10/28/lightweight-compression.html 。这些都是 OLAP 数据库以及相关领域常见的套路,经典的产品如 DB2、Redshift 等都搞过。我也在多个项目中采取了类似的实现。

Sort

DuckDB 对排序操作也花了不少心思。数据库系统的内排序、外排序、多列排序、变长字符串排序、多线程并行排序、以及 Pointer Swizzling 等花样都用上了。实测效果看起来还不错,打败了 pandas、SQLite、Hyper、ClickHouse 等一众选手。其实字符串排序最大的性能杀手是以汉字为代表的字符串:拼音序、笔划序,甚至莫名其妙的自定义顺序。数值类型的排序性能杀手应该是 NUMERIC:https://duckdb.org/2021/08/27/external-sorting.html 。需要更多细节的话,可以读读这个小论文:http://www.bicod.uk/papers/BICOD21_paper_9.pdf

Window Function

Window 函数(窗口函数)是 SQL 中做 OLAP 分析常见的特性,它的代表关键字是 OVER。最简单暴力的执行方式需要根据开窗的属性对数据排序、分段计算需要的统计值。数据一旦涉及到排序就很可能快不起来,毕竟它的复杂度通常是 nlgn。Hash 分段、并行执行、预聚合都是比较容易想到的加速方式。博客 https://duckdb.org/2021/10/13/windowing.html 中有详细一些的例子,还有参考论文如Efficient Processing of Window Functions in Analytical SQL Queries 。

Fulltext Search

DuckDB 在 2021 年 1 月的博客 https://duckdb.org/2021/01/25/full-text-search.html 中就介绍了其对全文检索的支持。全文检索在 OLTP 型的数据库中也大多有支持,但是效果并不是特别好。在 OLAP 系统中支持全文检索则更是一个比较普遍的需求,毕竟很多数据都是文档或 JSON 等半结构化的数据。除了 Elastic Search、Solr 这种专门做检索的系统之外,支持全文检索的 OLAP 类系统也越来越多了。数据库中要做全文检索,最麻烦的其实是数据的准备和导入。最简单粗暴的办法是直接把文档丢到一个长的文本字段中去。DuckDB 的博客给出的是 TREC 这个著名的检索领域评测大会的测试集,需要做一些转换,将数据加载到 DuckDB 内。

Modern Data Stack

DuckDB 又来赶时髦了。它弄了个单机版的 Modern Data Stack 的例子:http://t.cn/A6oNI4pK,Modern Data Stack in a Box with DuckDB。软件栈里头全是时髦的组件,包括:Meltano, DuckDB, dbt, Apache Superset。甚至为了跑 Superset 弄上了 Windows 的 WSL。为了把 SQL 和 ETL 或 ELT 之类的数据管道搞好,大家也是花样百出,各领风骚。

Latest Version

DuckDB 发布的速度挺快,已经到 0.60 版本了:https://duckdb.org/2022/11/14/announcing-duckdb-060.html ,改进了存储格式、压缩算法、数据加载、内存管理、索引创建,甚至 shell 语法提示和结果集快速展现。居然也支持不带 SELECT 关键字的查询,以及 ClickHouse 那个搞怪的 COLUMN 扩展语法。

Written on November 20, 2022