什么是DuckDB?
DuckDB是一个免费开源的嵌入式数据库管理系统,专为数据分析和在线分析处理而设计。这意味着几个方面:
- 它是免费和开源软件,任何人都可以使用和修改代码。
- 它是嵌入式的,意味着数据库管理系统(DBMS)在与使用它的应用程序相同的进程中运行。这使得它快速且简单易用。
- 它针对数据分析和OLAP(在线分析处理)进行了优化,而不仅仅是典型数据库中的事务数据。这意味着数据是按列而不是行组织的,以优化聚合和分析。
- 它支持标准SQL,因此您可以在数据上运行查询、聚合、连接和其他SQL函数。
- 它在应用程序内部以进程方式运行,而不是作为单独的进程。这消除了进程间通信的开销。
- 像SQLite一样,它是一个简单的基于文件的数据库,因此不需要单独的服务器安装。您只需将库包含在应用程序中即可。
总之,DuckDB为需要快速简单数据分析能力的应用程序提供了易于使用的嵌入式分析数据库。它填补了在分析处理中使用完整数据库服务器过度的空白。
为什么DuckDB变得越来越受欢迎?
有很多原因导致公司现在正在构建基于DuckDB的产品。该数据库专为快速分析查询而设计,这意味着它针对聚合、连接和大型数据集上的复杂查询进行了优化 – 这些是在分析和报告中经常使用的查询类型。此外:
- 安装、部署和使用都很简单。没有需要配置的服务器 – DuckDB在您的应用程序内部嵌入运行。这使得它易于集成到不同的编程语言和环境中。
- 尽管简单,DuckDB具有丰富的功能集。它支持完整的SQL标准、事务、二级索引,并与流行的数据分析编程语言(如Python和R)良好集成。
- DuckDB对任何人都是免费的,可以修改,这降低了开发人员和数据分析师采用的门槛。
- DuckDB经过了充分的测试并且稳定。它有一个广泛的测试套件,并且在各种平台上进行持续集成和测试以确保稳定性。
- DuckDB提供了与专门的OLAP数据库相当的性能,同时更易于部署。这使它适用于小到VoAGI数据集的分析查询,也适用于大型企业数据集。
简而言之,DuckDB结合了SQLite的简单易用性和专门的列式数据库的分析性能。这些因素 – 性能、简单性、功能和开源许可证 – 为DuckDB在开发人员和数据分析师中的日益增长的受欢迎程度做出了贡献。
DuckDB的Python示例
让我们使用Python API来测试一下DuckDB的几个功能。
您可以使用Pypi安装DuckDB:
pip install duckdb
对于其他编程语言,请参阅DuckDB的安装指南。
在这个例子中,我们将使用Kaggle上的Data Science Salaries 2023 CSV数据集,尝试测试DuckDB的各种功能。
关系API
您可以像pandas一样将CSV文件加载到关系中。DuckDB提供了一个关系API,允许用户将查询操作链接在一起。这些查询是惰性评估的,从而使DuckDB能够优化它们的执行。
我们已经加载了数据科学工资数据集并显示了别名。
import duckdb
rel = duckdb.read_csv('ds_salaries.csv')
rel.alias
'ds_salaries.csv'
要显示列名,我们将使用.columns
,与pandas类似。
rel.columns
['工作年限',
'经验级别',
'雇佣类型',
'职位标题',
'薪水',
'薪水货币',
'薪水(美元)',
'雇员居住地',
'远程比例',
'公司位置',
'公司规模']
您可以对关系应用多个函数以获得特定结果。在我们的例子中,我们过滤了“工作年限”,只显示了三列,并对它们进行了排序和限制,以显示基于薪水的底部五个职位标题。
通过参考指南,了解更多关于关系型API的信息。
rel.filter("工作年限 > 2021").project(
"工作年限,职位标题,薪水(美元)"
).order("薪水(美元)").limit(5)
┌───────────┬─────────────────┬───────────────┐
│ 工作年限 │ 职位标题 │ 薪水(美元) │
│ int64 │ varchar │ int64 │
├───────────┼─────────────────┼───────────────┤
│ 2022 │ NLP 工程师 │ 5132 │
│ 2022 │ 数据分析师 │ 5723 │
│ 2022 │ BI 数据分析师 │ 6270 │
│ 2022 │ AI 开发者 │ 6304 │
│ 2022 │ 数据分析师 │ 6359 │
└───────────┴─────────────────┴───────────────┘
您还可以使用关系型API来连接两个数据集。在我们的例子中,我们通过更改“职位标题”的别名来连接相同的数据集。
rel2 = duckdb.read_csv('ds_salaries.csv')
rel.set_alias('a').join(rel.set_alias('b'), '职位标题').limit(5)
┌───────────┬──────────────────┬─────────────────┬───┬──────────────┬──────────────────┬──────────────┐
│ 工作年限 │ 经验级别 │ 雇佣类型 │ ... │ 远程比例 │ 公司位置 │ 公司规模 │
│ int64 │ varchar │ varchar │ │ int64 │ varchar │ varchar │
├───────────┼──────────────────┼─────────────────┼───┼──────────────┼──────────────────┼──────────────┤
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 美国 │ 大 │
│ 2023 │ 机器学习工程师 │ 合同 │ ... │ 100 │ 美国 │ 小 │
│ 2023 │ 机器学习工程师 │ 合同 │ ... │ 100 │ 美国 │ 小 │
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 美国 │ 小 │
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 美国 │ 小 │
├───────────┴──────────────────┴─────────────────┴───┴──────────────┴──────────────────┴──────────────┤
│ 共 5 行 21 列 (显示 6 列) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────┘
直接使用SQL方法
还有直接的方法。您只需编写SQL查询来对数据集进行分析。与表名不同,您将写入CSV文件的位置和名称。
duckdb.sql('SELECT * FROM "ds_salaries.csv" LIMIT 5')
┌───────────┬──────────────────┬─────────────────┬───┬──────────────┬──────────────────┬──────────────┐
│ 工作年限 │ 经验级别 │ 雇佣类型 │ ... │ 远程比例 │ 公司位置 │ 公司规模 │
│ int64 │ varchar │ varchar │ │ int64 │ varchar │ varchar │
├───────────┼──────────────────┼─────────────────┼───┼──────────────┼──────────────────┼──────────────┤
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 西班牙 │ 大 │
│ 2023 │ 机器学习工程师 │ 合同 │ ... │ 100 │ 美国 │ 小 │
│ 2023 │ 机器学习工程师 │ 合同 │ ... │ 100 │ 美国 │ 小 │
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 加拿大 │ 中 │
│ 2023 │ 软件工程师 │ 全职 │ ... │ 100 │ 加拿大 │ 中 │
├───────────┴──────────────────┴─────────────────┴───┴──────────────┴──────────────────┴──────────────┤
│ 共 5 行 11 列 (显示 6 列) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────┘
持久存储
默认情况下,DuckDB在内存数据库上运行。这意味着创建的任何表都存储在内存中,并且不会持久化到磁盘上。然而,通过使用.connect()
方法,可以连接到磁盘上的持久数据库文件。写入到该数据库连接的任何数据将保存到磁盘文件,并在重新连接到同一文件时重新加载。
- 我们将使用
.connect()
方法创建一个数据库。 - 运行一个SQL查询来创建一个表。
- 使用查询添加两条记录。
- 显示新创建的测试表。
import duckdb
con = duckdb.connect('kdn.db')
con.sql("CREATE TABLE test_table (i INTEGER, j STRING)")
con.sql("INSERT INTO test_table VALUES (1, 'one'),(9,'nine')")
con.table('test_table').show()
┌───────┬─────────┐
│ i │ j │
│ int32 │ varchar │
├───────┼─────────┤
│ 1 │ one │
│ 9 │ nine │
└───────┴─────────┘
我们还可以使用数据科学薪资CSV文件创建新表。
con.sql('CREATE TABLE ds_salaries AS SELECT * FROM "ds_salaries.csv";')
con.table('ds_salaries').limit(5).show()
┌───────────┬──────────────────┬─────────────────┬───┬──────────────┬──────────────────┬──────────────┐
│ work_year │ experience_level │ employment_type │ ... │ remote_ratio │ company_location │ company_size │
│ int64 │ varchar │ varchar │ │ int64 │ varchar │ varchar │
├───────────┼──────────────────┼─────────────────┼───┼──────────────┼──────────────────┼──────────────┤
│ 2023 │ SE │ FT │ ... │ 100 │ ES │ L │
│ 2023 │ MI │ CT │ ... │ 100 │ US │ S │
│ 2023 │ MI │ CT │ ... │ 100 │ US │ S │
│ 2023 │ SE │ FT │ ... │ 100 │ CA │ M │
│ 2023 │ SE │ FT │ ... │ 100 │ CA │ M │
├───────────┴──────────────────┴─────────────────┴───┴──────────────┴──────────────────┴──────────────┤
│ 5 行 11 列 (显示 6 列) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────┘
执行所有任务后,必须关闭与数据库的连接。
con.close()
结论
为什么我喜欢DuckDB?它快速简单易学易管理。我相信简单性是DuckDB在数据科学界广泛使用的主要原因。DuckDB提供了直观的SQL接口,对于数据分析师和科学家来说很容易上手。安装简单,数据库文件轻量且易于管理。所有这些使DuckDB使用起来非常愉快。
请查看我之前在Deepnote上关于使用DuckDB进行数据科学的深度分析的文章。
在数据加载、管理和分析方面提供了强大的工具,与其他数据库解决方案相比,DuckDB提供了一种有吸引力的选择。我相信随着更多数据专业人员发现其用户友好性,DuckDB将在未来几年继续吸引用户。Abid Ali Awan (@1abidaliawan)是一位持有认证的数据科学家,热衷于构建机器学习模型。目前,他专注于内容创作,并在机器学习和数据科学技术方面撰写技术博客。Abid拥有技术管理硕士学位和电信工程学士学位。他的愿景是利用图神经网络为患有心理疾病的学生构建一个AI产品。