网易首页 > 网易号 > 正文 申请入驻

使用 DuckDB 的进程中分析数据管理

0
分享至

作者 | Hannes Mühleisen

译者 | 马可薇

策划 | Tina

摘要

  • DuckDB 是一款专为分析数据管理设计的开源 OLAP 数据库,与 SQLite 类似,这是一款可被嵌入到应用中的进程中数据库。

  • 进程中的数据库引擎处于应用之中,允许同一内存地址空间内的数据传输,不再需要通过套接字复制大量数据,从而提升了性能。

  • DuckDB 利用矢量处理查询,允许在 CPU 缓存中的有效操作,最小化函数调用开销。

  • DuckDB 所使用的小块数据驱动(Morsel-Driven)的并行,允许在多个核心上有效并行化的同时,保留对对核心处理的认知。

我为什么要踏上这条构建新数据库的旅程?这还要从著名统计学家和软件开发者 Hadley Wickham 的一句话说起:


把能放到内存中的数据放到数据库中是没有任何好处的,只会更慢更让人头疼。

这句话对我们这些数据库研究者而言既是打击也是挑战。是什么让数据库变得慢且头疼呢?罪魁祸首首先要数客户端 - 服务器模式。

在进行数据分析、将大量数据从应用转移至数据库,或者是将数据从数据库中提取到 R 或 Python 这类分析环境中时,整个过程可能会慢到折磨。

我曾试图理解客户端 - 服务器这一架构模式的起源,并撰写了论文《不要挟持我的数据——客户端协议重设案例》。

我对比了各类数据管理系统中的数据库客户端协议,计算了在客户端程序和不同数据库系统中,传输固定大小数据集所需要的时间。

我以 Netcat 工具通过网络套接字传输相同数据集的情况作为基准:

图一:不同客户端的对比,虚线为 Netcat 传输 CSV 数据所需的实际时间

对比 Netcat,MySQL 传输同样大小的数据需要十倍长的时间,Hive 和 MongoDB 则需要超过一个小时的时间。这个客户端 - 服务器模式似乎充满了问题。

SQLite

我又想起了 SQLite,坐拥数十亿份拷贝的 SQLite 无疑是世界上使用最为广泛的 SQL 系统。它们几乎时无处不在,人们每天都在与几十、乃至上百的实例打交道,但却意识不到。

SQLite 在进程中运行,这种不同以往的架构方式将数据库的管理系统直接整合到客户端应用之中,避免了传统的客户端 - 服务器模式。数据可直接在同一内存地址中进行传输,不再需要通过套接字复制和序列化大量数据。

然而,SQLite 并不是为大规模数据分析而设计,它的主要目的是为处理事务性工作负载。

DuckDB

几年之前,Mark Raasveldt 和我一同开始研究新数据库 DuckDB。DuckDB 是完全由 C++ 编写数据库管理系统,采用矢量执行引擎,作为一款进程中数据库引擎,我们常常称其为“分析性 SQLite”。该项目在极其宽松的 MIT 许可下发布,由基金会管理运作,而不是传统的风险投资模式。

DuckDB 的交互是什么样的?

import duckdb
duckdb.sql('LOAD httpfs')
duckdb.sql("SELECT * FROM 'https://github.com/duckdb/duckdb/blob/master/data/parquet-testing/userdata1.parquet'").df()

在这短短几行中,DuckDB 以 Python 包的形式导入,加载了一个扩展以实现与 HTTPS 资源的通信,通过 URL 读取了一份 Parquet 文件并将其转换为 Panda 数据框架(DF)。正如这个例子中所示,DuckDB 可直接支持 Parquet 文件,我们将其视作是新版 CSV 文件。LOAD httpfs调用则展示了 DuckDB 是如何通过插件进行扩展。

DF 的转换过程中隐含了许多复杂的工作,涉及到一个可能包含几百万行结果集的传输。但由于是在同一地址空间内进行的操作,我们可以绕过序列化或套接字传输,让整个过程快到难以置信。

我们还开发了一个具备查询语句自动完成和 SQL 语法高亮等功能的命令行客户端。例如,我在电脑上启动一个 DuckDB shell,读取同一个 Parquet 文件:

如果想用这条查询语句:

SELECT * FROM userdata.parquet;

会发现传统的 SQL 系统在这里通常不太行。userdata.parquet是个文件而不是表,没有 userdata.parquet 这张表,但却有这个 Parquet 文件。如果找不到叫这个名字的表,DuckDB 会搜索该名称的其他实体并执行查询语句,如 Parquet 文件。

进程中分析

从架构的角度来说,DuckDB 有一个新的数据管理系统类别:进程中 OLAP 数据库。

SQLite 是面向 OLTP(在线事务处理)的进程中系统,但对于传统 OLTP 客户端 - 服务器架构而言,PostgreSQL 反而是更常见的选择。

图二:OLTP 对比 OLAP

对于 OLAP 而言,客户端 - 服务器系统有不少的可选项,其中便有最为公认的开源选项 ClickHouse。但在 DuckDB 出现之前,进程中 OLAP 还没有任何选项可言。

DuckDB 的技术方面

让我们来看看 DuckDB 的技术层面,从下面这条 SQL 语句的处理阶段开始:

图三:DuckDB 中的一条简单选择语句

在这段示例中,我们从共用cid列的customersale这两张表的 JOIN 中选择名字和总和,通过将客户(customer)的所有收入和交易的税金相加,从而计算每个客户的总收入。

在运行这条语句时,系统会将两张表相连(JOIN),根据cid列的值对客户进行汇总。随后系统会计算对应的revenue + tax,再按照cid进行分组聚合,从而得出名字和最终总和。

DuckDB 对这条语句的处理有如下几个标准阶段:查询规划、查询优化、物理规划。其中查询规划阶段又被进一步划分为所谓的管道。

举例来说,这段查询有三个管道,由它们在流中运作的方式定义。流在中断操作符,也就是需要取回全部输入时结束。

图四:第一管道

首条管道负责扫描customer表并构建一个哈希表。哈希的连接(join)被分为两个阶段,构建哈希列表和探测。哈希表的构建通常需要能接触到 join 左侧的所有数据,也就是说customer表必须全部被执行并输入到hash join build阶段。这一管道完成后,我们将进入第二管道。

图五:第二管道

第二条管道更大且包含更多流运算符:可扫描sales表,查看上一步构建的哈希表,从customer表中找到相连的伙伴,随后对revenue + tax一行进行对应并执行聚合以及中断操作符,最后再执行group by build阶段从而完成第二管道。

图六:第三管道

我们可以让第三和最后一条管道,使其读取GROUP BY的结果并输出最终结果。这是段非常标准的过程,许多数据库都采取了类似的查询规划方法。

一次一行

要想理解 DuckDB 对查询语句的处理,让我们先看看传统火山迭代模型是如何在一系列迭代器中,让所有操作符都以一个迭代器为输入的同时暴露另一个迭代器。

语句的执行从最上层的运算符读取开始,也就是例子中的GROUP BY BUILD阶段。但此时因为还没有任何数据进入,所以它还读取不到任何东西。这也就触发了对其子运算符(映射)的读取请求,后者再从它自己的子运算符HASH JOIN PROBE中读取,该过程会逐级向下,直到最终的sale表。

图七:火山迭代模型

sale 表会生成一个元组以代表 ID、收入(revenue)以及税款这三列,比如421233422。该元组会向上移动到HASH JOIN PROBE并查询其建立的哈希表。比如,在知道ID 42对应的是 ASML 公司后,它会生成新的一行作为连接结果,也就是ASML123342

新生成的这一行随后会被下一个运算符处理,映射运算符会将最后两列相加,从而生成新的一行:ASML1355。这一行最终会进入GROUP BY BUILD阶段。

这种一次一个元组、一次一行,以“行”为重点的方式在 PostgreSQL、MySQL、Oracle、SQL 服务器,以及 SQLite 等众多数据库系统中都很常见,在事务性用例中非常有效,但却在数据分析处理方面存在一个明显的弱点:在运算符和迭代器之间的不断切换,会产生巨大的开销。

理论上来说是可以通过及时(JIT)编译整条流水线,这条方案虽然可行,但却不是唯一的解决方案。

一次一矢量

让我们考虑简单的流式运算符操作,比如映射。

图八:映射的实现

我们将传入一行和部分伪代码:input.readRow会读取一行输入,将第一个数值不变,但输出的第二个值会变成输入的第二和第三个相加之和,随后这行输出会被写入。这种方式虽然实施起来简单,但由于每一次数值读取都需要函数调用,因此会产生巨大的性能成本。

这种“一次一行”模型可优化为“一次一矢量”模型,该模型概念首次于 2005 年的“MonetDB/X100:超管道查询执行”中被首次提出。

对这类模型而言,每次处理的不再是单一的值,而是被统称为矢量的几列;每次处理的也不是一行中的一个值,而是列中的多个值。类型的切换是在多个值的矢量中进行,而不是单行数值上,因此这种方式可减少开销。

图九:“一次一矢量”模型

“一次一矢量”模型在列和行的执行之间找到了平衡点。按列执行的高效性是以内存为代价的,通过将列的数量控制在一定范围内,这种“一次一矢量”模型能避免 JIT 编译的同时,促进局限性缓存,后者对效率而言是至关重要的。

在著名的“人人都应知道的延迟数据”中展示了缓存局限性的重要性。

图十:人人都应知道的延迟数据

这张图由谷歌的 Peter Norvig 和 Jeff Dean 提出,高亮了 L1 缓存引用(0.5 纳秒)和猪内存引用(100 纳秒)之间差距为 200 倍。而考虑到 1990 年起 L1 的缓存引用就已经快了 200 倍,而内存引用只加快了两倍,将操作放在 CPU 缓存中是具有极大优势的。

这也就是矢量查询的魅力所在。

图十一:通过矢量查询处理实现映射

让我们再回到之前的 revenue + tax 映射例子。这次我们不再只取一行,而是用三个矢量值作为输入,两个矢量作为输出。我们读取的不再是之前的一行,而是一小块数据(多个矢量列的集合)。第一个矢量保持不变,并被重新分配至输出;随后再创建新的结果矢量,对 0 到 2048 范围内的每一个单独值进行加法运算。

这种方式允许编译器自动插入特殊指令,仅在矢量级进行的数据类型解释和转换也避免了函数调用的开销。这就是矢量处理的核心所在。

并行交换

单 CPU 的高效率对矢量处理而言还不够好,它还需要能在多个 CPU 上有良好的表现。我们又是如何支持并行的呢?

谷歌首席科学家 Goetz Graefe 在他的论文《火山——可扩展的并行查询评估系统》中描述了交换器并行的概念。

图十二:交换运算符的并行

在这个例子中,三个分区同时读取。应用过滤器、数据预聚合,之后再哈希。数据根据哈希值被分割,进一步聚合、重聚合,最后输出被合并。这样一来,查询的大部分都能被有效地并行化。

举例来说,这种方式在 Spark 执行简单语句时就有用到。在完成文件扫描后,一个哈希聚合器会执行partial_sum,随后一个独立的操作会对数据进行分割、重聚合从而计算出总和。然而,这在很多情况下有被证明是会出问题的。

小块数据驱动的并行

在 SQL 引擎中实现并行化更为现代的模型是“小块数据驱动(Morsel-Driven)的并行”。与前文提到的方式类似,输出层面的扫描被分割,从而实现部分扫描。在我们的第二条管道中,我们有两次对sale表的部分扫描,第一次扫描前半部分,第二次扫描剩下半部分。

图十三:小块数据驱动的并行

其中,HASH JOIN PROBE维持不变,因为它是从两条管道中对同一哈希表进行操作。映射操作独立进行,所有结果都会被同步到GROUP BY操作符中,也就是我们的阻塞操作符。注意看,这里我们没有用到任何一个交换操作符。

与基于交换操作符的传统模型不同,GROUP BY知道并行的存在,且可有效地管理不同线程读取可能存在冲突的分组所导致的问题。

十四:分割哈希表以实现并行合并

在小块数据驱动的并行中,每个线程都会在流程开始时(第一阶段)预先聚合其数值,输入数据的独立子集活小块数据会被构建在独立的哈希表中。

下一阶段(第二阶段)中涉及分区聚合:在本地哈希表中,数据根据组键的基数进行分区,以确保每个哈希表中不会包含其他哈希表中的键值。在读取完成所有数据后,就可以最终确定哈希表和聚合,我们从每个参与的线程中选择相同的分区,并规划更多的线程将其全部读取。

虽然整体过程比标准的哈希表聚合还要复杂,但这却能允许小块数据为驱动的模型实现极大的并行性。该模型可有效地在多个输入上构建聚合,避免了交换操作符所带来的相关问题。

简单的基准测试

我通过文中演示的查询示例,再加上ORDER BYLIMIT子句进行了一个简单的基准测试。SQL 语句从customersale表中选择namerevenue + tax的综合,这两张表通过customer进行分组和连接。

实验涉及两张表,其中一张有一百万的客户数,另一张则有上亿条销售记录。相当于 1.4 GB 的 CSV 数据,数据大小刚刚好。

图十五:简单的基准测试

DuckDB 只需要半秒就可以在我的笔记本上完成查询,但 PostgreSQL 却在我优化了配置后花费 11 秒才完成任务,默认配置下则需要 21 秒。

虽然 DuckDB 的查询处理速度比 PostgreSQL 快 40 倍左右,但别忘了这种对比并不公平,PostgreSQL 主要还是为 OLTP 工作负载而设计的。

结 论

本文是为解释 DuckDB 的设计、功能和原理而编写。作为一款封装紧实的数据引擎,Duck DB 可以库的形式直接与应用程序相连,它的足迹小且无依赖性,允许开发人员将其轻松继承为一个可用于分析的 SQL 引擎。

我着重强调了进程内数据库的强大之处在于,其能有效将结果集转移至客户端并将结果写入数据库。

DuckDB 设计的一个重要组成部分在于矢量查询处理,这种技术允许高效的缓存内操作,消除了函数调用所带来的开销负担。

最后,我对 DuckDB 的并行模型也有谈及。小块数据驱动的并行模型允许跨任意数量核心的高效并行化的同时,也能维持对多核处理的认知,有助于提高 DuckDB 整体的性能和效率。

查看英文原文:

In-Process Analytical Data Management with DuckDB(https://www.infoq.com/articles/analytical-data-management-duckdb/)

声明:本文为 InfoQ 翻译,未经许可禁止转载。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
上任后迎新难题!穆里尼奥遇魔鬼赛程,欧冠一胜难求,将对阵皇马

上任后迎新难题!穆里尼奥遇魔鬼赛程,欧冠一胜难求,将对阵皇马

祥谈体育
2025-09-19 10:50:15
翟欣欣涉敲诈勒索案一审宣判

翟欣欣涉敲诈勒索案一审宣判

界面新闻
2025-09-19 10:30:40
1450. 马里乌波尔空运行动

1450. 马里乌波尔空运行动

燃烧的岛群
2025-09-20 09:09:30
中检西部李宝基:20%电动车不合格,印度摩托质量远超自主

中检西部李宝基:20%电动车不合格,印度摩托质量远超自主

经济观察报
2025-09-19 07:54:06
打没打残哈马斯真主党阿萨德伊朗,要完控西岸,只剩胡赛了

打没打残哈马斯真主党阿萨德伊朗,要完控西岸,只剩胡赛了

邵旭峰域
2025-09-17 10:58:49
浙江省公安厅党委专职副书记王建已任省委巡视组组长

浙江省公安厅党委专职副书记王建已任省委巡视组组长

澎湃新闻
2025-09-19 21:48:27
为什么说人类去ktv就几乎废了?网友:我只能说还是注意安全吧

为什么说人类去ktv就几乎废了?网友:我只能说还是注意安全吧

解读热点事件
2025-06-10 00:20:03
斯诺登棱镜门事件,美国CIA派十六名特种兵进入澳门,结局如何

斯诺登棱镜门事件,美国CIA派十六名特种兵进入澳门,结局如何

神奇的锤子
2024-09-18 11:27:13
小米宣布空调10年免费包修,格力高管diss

小米宣布空调10年免费包修,格力高管diss

证券时报e公司
2025-09-19 23:18:41
警花张津瑜已经结婚生子网传一家人开心吃饭照片和吕总恩怨已消散

警花张津瑜已经结婚生子网传一家人开心吃饭照片和吕总恩怨已消散

深度报
2025-09-19 20:47:32
全球媒体聚焦丨“美国炸弹曾落下的地方,竖起了中国风机”

全球媒体聚焦丨“美国炸弹曾落下的地方,竖起了中国风机”

国际在线
2025-09-19 17:57:57
28岁女子去中东旅游被渴死,父母:不收尸,就让她死在国外吧

28岁女子去中东旅游被渴死,父母:不收尸,就让她死在国外吧

罪案洞察者
2025-09-03 13:58:14
南京博物院镇馆之宝:价值9亿的金簪,竟只是16岁小妾的陪葬物

南京博物院镇馆之宝:价值9亿的金簪,竟只是16岁小妾的陪葬物

悦悦侃历史
2025-09-10 15:03:07
36年前陈宝国主演的盗墓恐怖片!尺度大到少儿不宜

36年前陈宝国主演的盗墓恐怖片!尺度大到少儿不宜

释凡电影
2025-08-14 09:33:19
女子20公里竞走杨家玉获第6亚洲失去争金点 西班牙佩雷斯卫冕成功

女子20公里竞走杨家玉获第6亚洲失去争金点 西班牙佩雷斯卫冕成功

劲爆体坛
2025-09-20 08:21:17
刚刚,突发地震!福建震感强烈!

刚刚,突发地震!福建震感强烈!

海峡网
2025-09-20 07:20:49
赖清德遭重大挫败,蒋万安起身访陆,关键时刻,董军发出最强震慑

赖清德遭重大挫败,蒋万安起身访陆,关键时刻,董军发出最强震慑

爱意随风起呀
2025-09-20 08:44:56
国羽丢1冠冲4金!男双全军覆没,2项或会师决赛,陈雨菲爆冷出局

国羽丢1冠冲4金!男双全军覆没,2项或会师决赛,陈雨菲爆冷出局

刘姚尧的文字城堡
2025-09-20 07:55:52
俄罗斯最怕的,从来都不是北约东扩,而是文化霸权覆灭

俄罗斯最怕的,从来都不是北约东扩,而是文化霸权覆灭

史政先锋
2025-09-17 13:50:20
武大终于换帅!而杨景媛没去香港,直播称状态很好,还要起诉网友

武大终于换帅!而杨景媛没去香港,直播称状态很好,还要起诉网友

热点菌本君
2025-09-19 18:12:37
2025-09-20 10:20:49
InfoQ incentive-icons
InfoQ
有内容的技术社区媒体
11516文章数 51477关注度
往期回顾 全部

科技要闻

字节跳动凌晨发布公告

头条要闻

日本开始一项"史无前例"行动:派多架战斗机前往欧洲

头条要闻

日本开始一项"史无前例"行动:派多架战斗机前往欧洲

体育要闻

亚洲天王效应 孙兴慜球衣售150万件破梅西纪录

娱乐要闻

全智贤被全面抵制!相关代言评论区沦陷

财经要闻

最重要的一个电话,信息量果然很大

汽车要闻

对话周光:一个技术理想主义者的“蜕变”

态度原创

旅游
时尚
教育
本地
军事航空

旅游要闻

热闻|清明假期将至,热门目的地有哪些?

推广|| 被低估的百元级国货!推荐你们趁好价试试

教育要闻

完善教师激励机制,激发教师教书育人的积极性

本地新闻

大学生军训哪家强,广西申请“出战”!

军事要闻

以军两个方向朝加沙城市中心推进

无障碍浏览 进入关怀版