常见问题解答 (FAQ)

ADBC 到底是什么?

ADBC 是

  • 一套用不同语言(C/C++、Go 和 Java,还有更多语言正在开发中)编写的抽象 API,用于处理数据库和 Arrow 数据。

    例如,ADBC 中查询的结果集都以 Arrow 数据流的形式返回,而不是逐行返回。

  • 一套用不同语言(C/C++、C#/.NET、Go、Java、Python 和 Ruby)编写的 API 实现,目标是不同的数据库(例如 PostgreSQL、SQLite,任何支持 Flight SQL 的数据库)。

为什么不直接使用 JDBC/ODBC?

JDBC 使用基于行的接口,如 ResultSet。当处理列式数据(如 Arrow 数据)时,这意味着我们必须至少转换一次数据,甚至可能转换两次

  • 一次(可能)在驱动程序或数据库中,将列式数据转换为基于行的格式,以便可以通过 JDBC API 返回。

  • 一次(总是)当客户端应用程序从 JDBC API 提取数据时,将行转换为列。

为了与 Arrow 的“零拷贝”或“最小拷贝”精神保持一致,我们希望避免这些不必要的转换。

ODBC 的情况类似。虽然 ODBC 确实支持 “按列绑定”,但并非所有 ODBC 驱动程序都支持它,并且使用起来更复杂。此外,ODBC 使用调用者分配的缓冲区(这通常意味着强制数据复制),并且 ODBC 指定的数据布局与 Arrow 不完全兼容(仍然需要数据转换)。

因此,我们认为仅扩展 ODBC 不足以满足 ADBC 的目标。ODBC 对于更广泛的数据库支持始终有价值,并且在 ODBC 之上提供基于 Arrow 的 API 很有用。ADBC 将允许在通用库中实现/优化此转换,为消费者提供更简单的接口,并提供一个 API,Arrow 原生系统或其他列式系统可以实现该 API 以绕过此包装器。

为什么 ODBC/Arrow 彼此不太合适

ODBC 通过 块游标 支持批量数据,并且 Turbodbc 证明了可以在其上构建性能良好的基于 Arrow 的 API。但是,它仍然与 Arrow 不太匹配

  • Null 值(“指示符”值)表示为整数,需要转换。

  • 结果缓冲区由调用者分配。这可能会强制不必要地复制数据。ADBC 改为使用 C 数据接口,尽可能消除复制(例如,如果驱动程序使用 Flight SQL)。

  • 某些数据类型以不同的方式表示,需要转换。SQL_C_BINARY 可以为合作的驱动程序和应用程序绕过此问题,但随后应用程序将不得不区别对待基于 Arrow 的和非基于 Arrow 的数据源。

    • 字符串必须以 null 结尾,这需要在 Arrow 数组中进行复制,或者要求应用程序处理数组中以 null 结尾的字符串。

    • 字符串是否可以嵌入 null 是由实现定义的,但 Arrow 指定 UTF-8 字符串,其中 0x00 是一个有效的字节。

    • 因为缓冲区由调用者分配,所以驱动程序和应用程序必须协作来处理大字符串;驱动程序必须截断该值,并且应用程序可以尝试再次获取该值。

    • ODBC 使用长度缓冲区而不是偏移量,需要与 Arrow 字符串数组进行另一种转换。

    • 时间间隔使用不同的表示形式.

ADBC 和 Arrow Flight SQL 有什么区别?

ADBC 是一个客户端 API 规范。它没有定义客户端和数据库之间发生的事情,只是定义了作为应用程序开发人员进行的 API 调用。在底层,驱动程序必须采用这些 API 调用并与实际数据库通信。另一种观点是,ADBC 完全是关于客户端的,并且没有指定关于网络协议或服务器端实现的任何内容。

Flight SQL 是一个网络协议。它指定了要发送到数据库以执行各种操作(如与数据库进行身份验证、创建预处理语句或执行查询)的确切命令。Flight SQL 指定了客户端和服务器必须实现的网络协议。

还有一种看待它的方式:可以为数据库编写 ADBC 驱动程序,纯粹作为客户端库。(例如,此存储库中的 PostgreSQL 驱动程序就是这样实现的,作为 libpq 的包装器。)但是,向数据库添加 Flight SQL 支持意味着要么修改数据库以运行 Flight SQL 服务,要么将数据库置于代理之后,该代理在 Flight SQL 和数据库之间进行转换。

为什么不直接使用 Arrow Flight SQL?

因为 ADBC 是客户端的,所以 ADBC 可以支持不返回 Arrow 数据或通过 Flight SQL 以外的协议支持 Arrow 数据的数据库。

那么我们甚至需要 Arrow Flight SQL 吗?

Flight SQL 是一个具体的协议,数据库供应商可以实现它,而不是设计他们自己的协议。并且 Flight SQL 还具有 JDBC 和 ODBC 驱动程序,以实现最大的兼容性。

作为一个类比:许多数据库实现了 PostgreSQL 网络协议,以便它们可以访问所有 PostgreSQL 客户端,包括 JDBC 和 ODBC 驱动程序。(并且 JDBC/ODBC 用户仍然可以使用其他驱动程序来处理其他数据库。)

对于 Arrow 生态系统,我们希望数据库实现 Flight SQL 网络协议,从而使他们可以访问所有 Flight SQL 客户端,包括 ADBC、JDBC 和 ODBC 驱动程序。(并且 ADBC 用户仍然可以使用其他驱动程序来处理其他数据库。)

那么什么是“ADBC Flight SQL 驱动程序”?

ADBC Flight SQL 驱动程序使用 Flight SQL 网络协议(数据库服务器公开)来实现 ADBC API 标准(应用程序与之交互)。因此,它是一个通用驱动程序,可以与许多数据库通信,只要这些数据库实现了 Flight SQL。

这有点不寻常,因为您会发现的大多数数据库驱动程序和数据库协议都是为特定数据库设计的。但是 Flight SQL 从一开始就被设计为与数据库无关的,ADBC 也是如此。

听起来它们有所重叠,但它们相互补充,因为它们在不同的抽象级别上运行。数据库开发人员可以只提供 Flight SQL 服务,这将免费为他们提供 ADBC、JDBC 和 ODBC 驱动程序,而无需自行构建和维护这些驱动程序。数据库用户可以只使用 ADBC 作为唯一的 Arrow 原生 API 来处理 Arrow 原生和非 Arrow 原生数据库,无论这些数据库是否支持 Flight SQL、自定义 Arrow 原生协议或任何 Arrow 原生协议。

那么什么是“ADBC JDBC 驱动程序”?

ADBC JDBC 驱动程序或假设的 ADBC ODBC 驱动程序将 JDBC API 适配到 ADBC API,以便 ADBC 用户可以与具有可用 JDBC API 的数据库进行交互。虽然这不能为您提供最佳性能(您需要为来回转换数据付费!),但它可以省去您自己编写这些转换的麻烦。

已经存在类似的库;例如,Turbodbc 将任何 ODBC 驱动程序包装在 Python 的 DBAPI (PEP 249) 中,而 arrow-jdbc 将任何 JDBC 驱动程序包装在定制的基于 Arrow 的 API 中。

所有这些 API 如何协同工作?

_images/AdbcQuadrants.mmd.svg

我们可以根据两个轴划分 API:Arrow 原生与面向行,以及特定于数据库与与数据库无关。

与数据库无关的 API 从供应商那里抽象出来,包括 ADBC、JDBC、ODBC,以及某种程度上的 Flight SQL。(如上所述,Flight SQL 仍然需要特定的供应商支持;xDBC 则不需要。)

特定于数据库的 API 由供应商为其系统制作,尽管其他系统最终可能会重新实现这些 API 以实现兼容性(PostgreSQL 网络协议通常这样做)。

Arrow 原生 API(如 ADBC、Flight SQL 和 BigQuery Storage API)原生返回 Arrow 数据,或更一般地说是列式数据。这可以为处理大量数据的应用程序提供性能优势。

面向行的 API(如 JDBC、ODBC 和 PostgreSQL 网络协议)一次处理一行。对于某些类型的应用程序来说,这可能更方便

什么是 ADBC 驱动程序管理器?

驱动管理器(在 C/C++ 中)是一个库,它实现了驱动 API,但在后台动态加载和管理多个驱动程序。它允许应用程序链接到单个库,但一次使用多个驱动程序。这避免了多个驱动程序之间的符号冲突,否则这些驱动程序将以相同的名称提供相同的 ADBC API。

有关深入了解,请参阅驱动程序和驱动程序管理器如何协同工作

什么是 ADBC SQL 方言?

这是一个陷阱问题!ADBC 不是 SQL 方言。ADBC 驱动程序需要做的,就是将您的查询字符串传递给数据库,并将结果集作为 Arrow 数据获取。在这方面,它类似于 JDBC。(ODBC 有一个它定义的“标准”SQL 方言;ADBC 没有这样做。)

对于一个试图解决定义与供应商无关的查询语言问题的项目,请参阅Substrait

下一次发布是什么时候?

没有固定的发布节奏。我们目前的目标是每 6-8 周发布一次。

一旦发布被标记,项目至少会留出 72 小时给 Arrow PMC 对发布进行投票。投票结束后,软件包将被上传到 PyPI、conda-forge 等地方。因此,即使在发布之后,二进制包可能也需要一段时间才能可用。

1.0 版本什么时候/在哪里发布?这个项目准备好了吗?

项目的不同部分有不同的版本号。我们认为某些实现(如 Go)已准备好 “1.0” 版本,而其他实现(如 Java)仍处于 pre-1.0 版本。 驱动程序实现状态 提供了单个驱动程序实现状态的粗略概述。

在哪里可以了解更多关于 ADBC 背后的原理?

请参阅相关工作