使用 turbodbc 将关系数据库连接到 Apache Arrow 世界


已发布 2017 年 6 月 16 日
作者 Michael König (MathMagique)

Michael Königturbodbc 项目 的主要开发者。

Apache Arrow 项目旨在成为面向列式数据处理系统的通用数据层,无需承担序列化成本或在更通用的层面上牺牲性能。尽管关系数据库在 Apache Arrow 的采用方面仍然滞后,但 Python 数据库模块 turbodbc 使用更 قدیمی、更专业的数据交换层:ODBC,为这些数据库带来了 Apache Arrow 支持。

ODBC 是一种数据库接口,为开发者提供了以行式或列式方式传输数据的选项。以前的 Python ODBC 模块通常使用行式方法,并且经常以重复的数据库往返来换取简化的缓冲区处理。这使得它们不太适合数据密集型应用程序,尤其是在与现代列式分析数据库交互时。

相比之下,turbodbc 从一开始就被设计为利用列式数据处理。自然,这意味着使用 ODBC API 的列式部分。然而,同样重要的是找到新的方法来向 Python 用户提供超出 Python PEP 249 规定的行式 API 能力的列式数据。Turbodbc 在最近发布的 2.0.0 版本中采用了 Apache Arrow 来完成这项任务。

>>> 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 表并填充缓冲值。
  • 重复前面的步骤,直到检索到整个结果集。

Data flow from relational databases to Python with turbodbc and the Apache Arrow frontend

在实践中,可以实现以下理想情况:一个 64 位整数列在列式数据库中存储为一个连续的内存块。通过网络传输大量的 64 位整数,ODBC 驱动程序将其直接写入 turbodbc 的 64 位整数缓冲区。Arrow 前端通过将整个 64 位缓冲区复制到 Arrow 表的 64 位整数列的空闲部分来累积这些值。

将数据从数据库移动到 Arrow 表,从而将其提供给 Python 用户,就像复制内存块一样简单,每次可以复制相当于数十万行的兆字节数据。由于没有序列化和转换逻辑,该过程极其高效。

一旦数据存储在 Arrow 表中,Python 用户就可以继续进行一些实际工作。他们可以将其转换为 Pandas DataFrame 进行数据分析(使用快速的 table.to_pandas()),将其传递给其他数据处理系统,例如 Apache SparkApache Impala(孵化中),或将其存储在 Apache Parquet 文件格式中。这样,非 Python 系统就可以有效地与关系数据库连接。

未来,turbodbc 的 Arrow 支持将扩展到使用更复杂的功能,例如 字典编码 的字符串字段。我们还计划尽可能选择小于 64 位的 数据类型。最后但同样重要的是,Arrow 支持将扩展到涵盖反向数据流,以便 Python 用户可以快速将 Arrow 表插入关系数据库。

如果您想了解更多关于 turbodbc 的信息,请查看 GitHub 项目项目文档。如果您想了解更多关于 turbodbc 如何实现具体细节的信息,请查看 Blue Yonder 技术博客上 “turbodbc 的制作” 系列的 第一部分第二部分