Apache Arrow DataFusion 26.0.0


已发布 2023年6月24日
作者 Apache Arrow PMC (pmc)

上次更新以来,DataFusion的开发经历了旋风般的六个月:社区不断壮大,增加了许多新功能,性能得到了提升,我们正在讨论将其独立为一个顶级的Apache项目。

背景

Apache Arrow DataFusion是一个可扩展的查询引擎和数据库工具包,使用Apache Arrow作为其内存格式,并用Rust编写。

DataFusion与Apache Calcite、Facebook的Velox及类似技术,都是下一代“解构数据库”架构的一部分,在这种架构中,新系统是建立在快速、模块化组件的基础上的,而不是作为一个单一紧密集成系统。

虽然像SparkDuckDBPola.rs这样单一紧密集成的系统是出色的技术,但我们的社区认为,任何在未来五年内开发新的数据密集型应用程序(例如机器学习中常见的应用程序)的人都需要一个高性能、向量化的查询引擎才能保持竞争力。在不投入数百万美元构建新的紧密集成引擎的情况下,获得此类技术的唯一实际方法是通过像DataFusion这样的开源项目,以及像Apache ArrowRust这样的赋能技术。

DataFusion主要面向创建其他数据密集型分析的开发者,并提供:

  • 高性能、原生、并行流式执行引擎
  • 成熟的SQL支持,包括子查询、窗口函数、分组集等功能
  • 内置对Parquet、Avro、CSV、JSON和Arrow格式的支持,并易于扩展以支持其他格式
  • 原生DataFrame API和Python绑定
  • 文档完善的源代码和架构,旨在根据下游项目需求进行定制
  • 高质量、易于使用的代码每两周发布到crates.io
  • 热情开放的社区,由备受推崇且广为人知的Apache软件基金会管理

本文的其余部分将重点介绍我们在过去六个月中对DataFusion进行的一些改进,并展望未来的发展方向。您可以在详细的更新日志中查看所有更改。

(甚至)更好的性能

各种基准测试表明,DataFusion在分析性能方面非常接近或甚至更快于最新技术水平(目前看来是DuckDB)。我们持续致力于提高性能(请参阅#5546了解列表),并乐意在这方面获得更多帮助。

DataFusion现在通过跨多个核心并行化,显著加快了单个大型Parquet文件的读取速度。由于arrow-rs上游JSON读取器CSV读取器的改进,读取JSON和CSV文件的原生速度也提高了2.5倍。

此外,我们将arrow-rs行格式集成到DataFusion中,从而使排序和合并速度提高了2-3倍

改进的文档和网站

壮大DataFusion社区的一部分是确保DataFusion的功能被理解,并且易于贡献和参与。为此,网站已经进行了清理,架构指南得到了扩展,路线图也得到了更新,并创建了几次概述性讲座

新功能

更多流式处理,更少内存

我们在流式执行路线图上取得了显著进展,例如无边界数据源流式分组、优化器中复杂的排序重新分区改进,以及对对称哈希连接的支持(有关此内容的更多信息,请参阅Synnada博客文章)。这些功能共同实现了两点:1)使使用DataFusion构建流式系统变得更容易,这些系统可以在看到输入结束之前(或从未看到)增量生成输出;2)允许通用查询使用更少的内存并更快地生成结果。

我们还改进了运行时内存管理系统,使DataFusion现在可以在其声明的内存预算内运行,从而生成运行时错误

DML支持(INSERTDELETEUPDATE等)

构建高性能数据系统的一部分是写入数据,DataFusion支持创建新文件的多项功能:

  • 支持内存和CSV表的INSERT INTOSELECT ... INTO
  • 用于将数据写入TableProviders的新API

我们正在努力提供更易于使用的COPY INTO语法,更好地支持写入parquet、JSON和AVRO,等等——有关更多详细信息,请参阅我们的跟踪史诗

时间戳和间隔

衡量一个SQL引擎成熟度的一个标志是它如何处理时间戳、日期、时间和间隔算术这个棘手的领域。DataFusion在此领域功能完善,并能如您所期望地运行,支持以下查询:

SELECT now() + '1 month' FROM my_table;

我们仍在致力于处理大量待改进的日期和时间功能

查询结构化类型(ListStruct

Arrow和Parquet很好地支持嵌套数据,DataFusion让您轻松查询此类StructList。例如,您可以使用DataFusion读取和查询用于探索性OLAP的JSON数据集 - Mendeley Data,如下所示:

----------
-- Explore structured data using SQL
----------
SELECT delete FROM 'twitter-sample-head-100000.parquet' WHERE delete IS NOT NULL limit 10;
+---------------------------------------------------------------------------------------------------------------------------+
| delete                                                                                                                    |
+---------------------------------------------------------------------------------------------------------------------------+
| {status: {id: {$numberLong: 135037425050320896}, id_str: 135037425050320896, user_id: 334902461, user_id_str: 334902461}} |
| {status: {id: {$numberLong: 134703982051463168}, id_str: 134703982051463168, user_id: 405383453, user_id_str: 405383453}} |
| {status: {id: {$numberLong: 134773741740765184}, id_str: 134773741740765184, user_id: 64823441, user_id_str: 64823441}}   |
| {status: {id: {$numberLong: 132543659655704576}, id_str: 132543659655704576, user_id: 45917834, user_id_str: 45917834}}   |
| {status: {id: {$numberLong: 133786431926697984}, id_str: 133786431926697984, user_id: 67229952, user_id_str: 67229952}}   |
| {status: {id: {$numberLong: 134619093570560002}, id_str: 134619093570560002, user_id: 182430773, user_id_str: 182430773}} |
| {status: {id: {$numberLong: 134019857527214080}, id_str: 134019857527214080, user_id: 257396311, user_id_str: 257396311}} |
| {status: {id: {$numberLong: 133931546469076993}, id_str: 133931546469076993, user_id: 124539548, user_id_str: 124539548}} |
| {status: {id: {$numberLong: 134397743350296576}, id_str: 134397743350296576, user_id: 139836391, user_id_str: 139836391}} |
| {status: {id: {$numberLong: 127833661767823360}, id_str: 127833661767823360, user_id: 244442687, user_id_str: 244442687}} |
+---------------------------------------------------------------------------------------------------------------------------+

----------
-- Select some deeply nested fields
----------
SELECT
  delete['status']['id']['$numberLong'] as delete_id,
  delete['status']['user_id'] as delete_user_id
FROM 'twitter-sample-head-100000.parquet' WHERE delete IS NOT NULL LIMIT 10;

+--------------------+----------------+
| delete_id          | delete_user_id |
+--------------------+----------------+
| 135037425050320896 | 334902461      |
| 134703982051463168 | 405383453      |
| 134773741740765184 | 64823441       |
| 132543659655704576 | 45917834       |
| 133786431926697984 | 67229952       |
| 134619093570560002 | 182430773      |
| 134019857527214080 | 257396311      |
| 133931546469076993 | 124539548      |
| 134397743350296576 | 139836391      |
| 127833661767823360 | 244442687      |
+--------------------+----------------+

无处不在的子查询

DataFusion可以通过将子查询重写为连接来运行许多不同的子查询。它在过去至少一年中能够运行所有TPC-H查询,但最近我们对该逻辑进行了重大改进,足以运行TPC-DS基准测试中的几乎所有查询。

社区和项目发展

上次更新以来的六个月里,DataFusion社区显著增长。在版本17.0.026.0.0之间,DataFusion合并了来自107位不同贡献者的711个PR,这还不包括所有核心依赖项(如arrowparquetobject_store)的工作,这些依赖项也得到了许多相同社区成员的支持。

此外,我们向 Apache Arrow 项目新增了 7 名提交者和 1 名 PMC 成员,他们主要专注于 DataFusion,我们也了解到一些使用 DataFusion 的炫酷新系统。鉴于社区的增长和对项目的兴趣,我们还澄清了使命声明,并正在讨论将 DataFusion“升级”为新的顶级 Apache 软件基金会项目。

如何参与

向社区中所有贡献了想法、讨论、错误报告、文档和代码的人致敬。与大家一起创新下一代数据库架构,令人兴奋!

如果您有兴趣为 DataFusion 做贡献,我们非常欢迎您的加入。您可以在自己的数据和项目中试用 DataFusion,并告诉我们您的体验,或者提交包含文档、测试或代码的 PR。适合初学者的开放问题列表在此处

查看我们的交流文档,了解更多与社区互动的方式。