Python API 简介
Python API是 DuckDB 的 Python 绑定。他实现了 Python DB-API 2.0
。
安装
DuckDB 需要 Python3.7 及以上版本
架构
DuckDB 的 Python API 提供了两套不同的架构:
- DB API: 实现了 Python 的 DB-API2.0 接口
- Relational API: 关系 API,它使用增量来构造查询,整个执行过程都是惰性的直到调用触发执行的方法,并且提供了 ORM 式的构造 SELECT 语句的方式
同时还提供了一些外围的核心组件:
- Types API: 用于隐式转换数据库数据类型和 Python 数据类型,并且提供了接口来构造复杂数据类型
- Function API: 为 DuckDB 绑定用户自定义过程函数(UDF)
- Expression API: 动态构造查询表达式
DBAPI 和 Relational API
他们是两种不同的工作模式,对于DB API实现了 Python DB-API 2.0 接口,标准的操作方式: duckdb.connect() → Connection.cursor() → Cursor.execute() -> Curosr.fetchall()
。
Relational API比较特殊,首先他只能执行数据查询语言即 SELECT 语句,并且他自身就是一个只读视图能够在查询语言中使用。
通常情况下任何一个查询操作都能够由两种操作方式实现:
Python
import duckdb
## DuckDBPyRelation 操作方式
# 惰性非阻塞,直接创建一个虚拟视图
rel = duckdb.sql("SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# 同样是惰性的,这就是不断调用来逼近需要的结果视图
# 同时 rel 是 DuckDBPyRelation 对象因此能够位于 sql 语句中
year_2011 = duckdb.sql("SELECT * FROM rel WHERE extract(year from 帖子发布时间)=2011")
# 执行读取操作来真正执行 SQL 语句
year_2011.fetch_df()
## DuckDBPyConnection 操作方式
# 直接在内存数据库中构建表,表中数据由 csv 文件构成
conn = duckdb.execute("CREATE TABLE new_table AS SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# 上面的等价操作
conn = duckdb.execute("SELECT * from read_csv('股吧数据-帖子详情(2010-2019)-版本3.csv',ignore_errors=True,max_line_size=20000000)")
# conn.table() 返回的就是 DuckDBPyRelation 对象,相当于在内存数据库中创建了表
new_table = conn.table()
# 执行查询
# 再次强调 FROM 后面必须是表,可以是 CREATE TABLE 创建的也可以是方法返回的 DuckDBPyRelation 对象
year_2011 = conn.execute("SELECT * FROM new_table WHERE extract(year from 帖子发布时间)=2011")
# 读取数据
year_2011.fetchall()
上面两种方式都实现了同一个结果,当时也有一些区别:
- DB API操作模式下,创建的表是真正存在于内存中或者 DuckDB 数据库文件中,他不会被释放,因此再次执行类似
conn.execute("SELECT * FROM new_table WHERE extract(year from 帖子发布时间)=2012")
这样的操作速度会非常块,因为不需要在读取 csv 来构建表了,但是这也意味着如果数据非常大会导致内存溢出 - Relational API操作模式下,并不会保存创建的表,虚拟视图在调用
year_2021.fetch_df()
后被释放了,也就是说没有办法复用表,再次执行类似命令还需要重新读取 csv
Python 生态交互
DuckDB 一个非常杀手锏的功能就是她与 Python 的整个生态进行了融合: