使用 turbodbc 将关系数据库连接到 Apache Arrow 世界
已发布 2017年6月16日
作者 Michael König (MathMagique)
Michael König 是 turbodbc 项目的首席开发者
Apache Arrow 项目旨在成为面向列式数据处理系统的通用数据层,无需产生序列化成本,也不会在更一般的层面上降低性能。虽然关系数据库在 Apache Arrow 的采用方面仍然落后,但 Python 数据库模块 turbodbc 使用一种更古老、更专业的数据交换层:ODBC,为这些数据库带来 Apache Arrow 支持。
ODBC 是一种数据库接口,它为开发者提供了以行式或列式方式传输数据的选项。 以前的 Python ODBC 模块通常使用行式方法,并且经常以重复的数据库往返操作来换取简化的缓冲区处理。 这使得它们不太适合数据密集型应用,尤其是在与现代列式分析数据库交互时。
相比之下,turbodbc 从一开始就被设计为利用列式数据处理。 自然地,这意味着使用 ODBC API 的列式部分。 然而,同样重要的是找到向 Python 用户提供列式数据的新方法,这些方法超出了 Python PEP 249 规定的行式 API 的功能。 Turbodbc 采用了 Apache Arrow 来完成这项任务,并发布了最新的 2.0.0 版本
>>> from turbodbc import connect
>>> connection = connect(dsn="My columnar database")
>>> cursor = connection.cursor()
>>> cursor.execute("SELECT some_integers, some_strings FROM my_table")
>>> cursor.fetchallarrow()
pyarrow.Table
some_integers: int64
some_strings: string
有了这个新功能,典型 SELECT 查询的结果集的数据流如下
- 数据库准备结果集,并使用行式或列式存储将其公开给 ODBC 驱动程序。
- Turbodbc 让 ODBC 驱动程序将结果集的块写入列式缓冲区。
- 这些缓冲区被公开给 turbodbc 的 Apache Arrow 前端。 此前端将创建一个 Arrow 表并填充缓冲的值。
- 重复前面的步骤,直到检索到整个结果集。
在实践中,可以实现以下理想情况:一个 64 位整数列作为一块连续的内存存储在列式数据库中。 大量的 64 位整数通过网络传输,ODBC 驱动程序直接将其写入 turbodbc 的 64 位整数缓冲区。 Arrow 前端通过将整个 64 位缓冲区复制到 Arrow 表的 64 位整数列的空闲部分来累积这些值。
将数据从数据库移动到 Arrow 表,从而将其提供给 Python 用户,可以像复制内存块一样简单,每次复制相当于数十万行的兆字节。 没有序列化和转换逻辑使得该过程非常高效。
一旦数据存储在 Arrow 表中,Python 用户就可以继续进行实际工作。 他们可以将其转换为 Pandas DataFrame 以进行数据分析(使用快速的 table.to_pandas()
),将其传递给其他数据处理系统,例如 Apache Spark 或 Apache Impala (孵化中),或将其存储在 Apache Parquet 文件格式中。 这样,非 Python 系统就可以有效地与关系数据库连接。
将来,turbodbc 的 Arrow 支持将扩展为使用更复杂的功能,例如 字典编码 字符串字段。 我们还计划尽可能选择小于 64 位的 数据类型。 最后但并非最不重要的一点是,Arrow 支持将扩展到涵盖数据流的反向方向,以便 Python 用户可以将 Arrow 表快速插入到关系数据库中。
如果您想了解有关 turbodbc 的更多信息,请查看 GitHub 项目和项目文档。 如果您想了解有关 turbodbc 如何实现具体细节的更多信息,请查看 “turbodbc 的制作”系列的第一部分和第二部分,网址为 Blue Yonder 的技术博客。