Apache Arrow Flight SQL:加速数据库访问

2022-02-17 16:53:51

2022年2月16日由何塞·阿尔梅达、詹姆斯·多昂、维尼修斯·弗拉加、朱塞利诺·朱塞利诺、大卫·李、凯尔·波特、拉斐尔·泰勒斯出版

我们想介绍Flight SQL,这是Apache Arrow社区开发的一种新的客户机-服务器协议,用于与SQL数据库交互,该数据库使用内存中的Arrow列格式和Flight RPC框架。

Flight SQL旨在提供与JDBC和ODBC等现有API大致相似的功能,包括执行查询;制作事先准备好的报表;以及获取有关支持的SQL方言、可用类型、已定义表等的元数据。然而,通过构建ApacheArrow,Flight SQL使客户端可以轻松地与Arrow本机数据库进行对话,而无需转换数据。通过使用Flight,它提供了一种有线格式的高效实现,该格式支持即时加密和身份验证等功能,同时允许进一步优化,如并行数据访问。

虽然它可以直接用于数据库访问,但不能直接替代JDBC/ODBC。相反,Flight SQL作为一个具体的有线协议/驱动程序实现,可以支持JDBC/ODBC驱动程序,并减少数据库的实现负担。

虽然像JDBC和ODBC这样的标准几十年来一直为用户提供良好的服务,但它们对于希望使用Apache Arrow或柱状数据的数据库和客户机来说是不够的。在这种情况下,基于行的API(如JDBC或PEP 249)需要转换数据,而对于本身是列式的数据库,这意味着数据必须转换两次,一次是为了在API中以行的形式呈现数据,一次是为了让使用者将数据返回到列中。与此同时,虽然ODBC等API确实提供了对结果缓冲区的批量访问,但这些数据仍必须复制到Arrow阵列中,以便与Turbodbc等项目实现的更广泛的Arrow生态系统一起使用。Flight SQL旨在摆脱这些中间步骤。

Flight SQL意味着数据库服务器可以实现一个标准接口,该接口从一开始就是围绕Apache Arrow和列数据设计的。就像Arrow提供标准内存格式一样,Flight SQL使开发人员无需设计和实现全新的wire协议。如前所述,Flight已经实现了一些功能,比如在线加密和请求认证,而数据库不需要重新实现这些功能。

对于客户端,Flight SQL提供了对查询结果的批量访问,而无需从其他API或格式转换数据。此外,通过将wire协议的实现工作推进到Flight和Flight SQL库中,需要为每种客户机语言或驱动程序编写的代码就更少了。通过使用Flight Underground,客户机和服务器可以合作实现优化,比如并行数据访问,这是Flight本身的最初目标之一。数据库可以将多个“端点”返回给Flight SQL客户端,然后客户端可以并行地从所有端点提取数据,从而使数据库后端能够水平扩展。

Flight SQL充分利用了Flight RPC框架及其可扩展性,通过Protobuf定义了额外的请求/响应消息。我们将简要地介绍一下飞行SQL协议,但是C++和java已经实现了管理这项工作的客户端。完整的协议可以在GitHub上找到。

客户端通过GetSchema RPC方法(获取响应的模式)或GetFlightInfo RPC方法(执行请求)发送请求。

请注意,虽然Flight SQL是作为Apache Arrow 7.0.0的一部分发布的,但它仍在开发中,详细的文档即将发布。然而,实现已经在C++和java中已经提供,它提供了一个低级别的客户端,可以使用以及可以实现的服务器骨架。

对于那些感兴趣的人来说,源代码中提供了一个包装Apache Derby的服务器实现和一个包装SQLite的服务器实现。还提供了一个演示客户端的简单CLI。最后,我们可以看一个执行查询和获取结果的简单示例:

flight::FlightCallOptions呼叫_options;//执行查询,获取描述如何获取结果的FlightInfo std::cout<<"执行查询:'" <&书信电报;标志_query<<"'" <&书信电报;std::endl;箭头_ASSIGN _或_RAISE(std::unique _ptr<;FlightInfo>;FlightInfo>;FlightInfo,客户端->;执行(调用_选项,标记_查询));//为(const flight::FlightEndpoint&;endpoint:flight_info->;endpoints())按顺序获取每个分区(尽管这可以并行完成){//这里我们假设每个分区都位于我们最初查询的同一台服务器上,但通常情况下并非如此:服务器可能会在我们必须连接的多台//其他服务器之间分割查询结果。//端点中的";票证";对客户端来说是不透明的。服务器使用它来//确定要返回的查询结果。箭头_ASSIGN _或_RAISE(自动流,客户端->;DoGet(调用选项,endpoint.ticket));//将所有结果读入箭头表,尽管我们可以在记录//批到达时迭代处理它们,以及std::shared_ptr<;箭头:表格>;桌子箭头_RETURN_NOT_OK(流->;ReadAll(&;table));标准:cout<<"读一个分区:"<&书信电报;std::endl;标准:cout<&书信电报;表->;ToString()<&书信电报;std::endl;}

与PyODBC等现有库相比,Arrow Flight已经快了20倍(约00:21:00)。Flight SQL将把这些性能优势打包成一个标准接口,供客户机和数据库实现。

预计将进一步完善和扩展协议。这项工作的一部分是使在飞行SQL上实现像JDBC这样的API成为可能;JDBC驱动程序正在积极开发中。虽然这再次引入了数据转换的开销,但这意味着通过实现Flight SQL,数据库可以让本机客户端和传统客户端都可以访问它自己。未来的其他改进可能包括Python绑定、ODBC驱动程序等。

对于任何有兴趣参与其中的人,无论是作为贡献者还是采用者,请联系邮件列表或加入GitHub上的讨论。