Apache DataFusion 成为查询 Apache Parquet 文件的最快单节点引擎

导航至

本博客最初发布于 Apache DataFusion 项目新闻与博客

我非常激动地宣布,Apache DataFusion 43.0.0 成为 ClickBench 中查询 Apache Parquet 文件的最快引擎。它比 DuckDBchDB/Clickhouse 在相同的硬件上都更快。这也标志着基于 Rust 的引擎首次占据榜首,此前该榜首一直由传统的基于 C/C++ 的引擎占据。 图 1:2024-11-16 ClickBench 结果,针对在 c6a.4xlarge(16 CPU/32 GB 内存)机器上,对分区后的 14 GB Parquet 数据集(100 个文件,每个文件约 140MB)进行的 ‘热’1 运行。测量结果是相对于使用不同硬件的结果(1.x)。

任何人现在都可以获得 Parquet 上的最佳性能。DataFusion 的开放式设计让您可以快速开始使用功能齐全的查询引擎,包括 SQL、数据格式、目录等,然后自定义您需要的任何行为。我预测,随着创建者可以将创新的重点放在查询语言、系统集成和数据格式等领域,而不是试图追赶核心引擎性能,新型数据系统将持续涌现。

ClickBench 还包括专有存储格式的结果,这些格式需要昂贵的加载/导出步骤,使其在较少的用例中才有用,因此远不如开放格式重要(尽管特定用例格式的想法很有趣2)。

这篇博客文章重点介绍了我们为实现此性能而使用的一些技术,并赞扬了所涉及的团队合作。

性能改进的强大历史

长期以来,性能一直是 DataFusion 社区的核心关注点,速度吸引着用户和贡献者。最近,我们似乎更加关注性能,包括在 2024 年 7 月,Mehmet Ozan KabakSynnada 的 CEO,再次 建议关注性能。这让我们中的许多人感到兴奋(谁不喜欢挑战!),随后我们团结起来,稳步提高每个版本的性能,如图 2 所示。 图 2:DataFusion 34(2023 年 12 月发布)和 DataFusion 43(2024 年 11 月发布)之间,ClickBench 性能提高了 30% 以上。

像所有好的优化工作一样,我们的工作也付出了持续的努力,因为 DataFusion 几年前就已经耗尽了 单次 2 倍的性能提升。我们来自世界各地3 和各种经验水平4 的工程师社区共同努力实现了这一目标(查看 此讨论 以了解情况)。它可能是一个 “流浪汉三明治”5,但它是一个美味的三明治!

当然,大多数这些技术以前都已实现和描述过,但直到现在,它们仅在专有系统中可用,例如 VerticaDataBricks PhotonSnowflake,或在紧密集成的开源系统中可用,例如 DuckDBClickHouse,这些系统并非旨在扩展。

StringView

当 DataFusion 切换到使用 Arrow StringView 时,所有查询的性能都得到了提高。使用 StringView “仅仅”节省了一些副本,并避免了某些比较的一次内存访问。但是,这些副本和比较恰好发生在查询处理期间的许多最热循环中,因此优化它们会带来明显的性能提升。

图 3: 来自 使用 StringView / 德式字符串使查询更快:第 1 部分 的图,显示了 StringView 如何在许多情况下节省复制数据。

使用 StringView 使 DataFusion 在 ClickBench 中更快需要大量的仔细的底层优化工作,这些工作在 使用 StringView / 德式字符串使查询更快:第 1 部分第 2 部分 中进行了描述。但是,它需要扩展 DataFusion 的其余操作以支持新类型。您可以通过查看 arrow-rs 中与 epic 链接的 100 多个拉取请求(此处)和 DataFusion 中的三个主要 epic(此处此处此处)来了解所需工作量的大小。

以下是参与该项目的人员的部分列表(对那些我忘记的人表示歉意)

Parquet

DataFusion 在 ClickBench 中的速度部分归功于(非常)快速地读取 Parquet 文件,这反映了在 Parquet 读取系统上投入的精力(请参阅使用毫秒级延迟查询 Parquet)。

DataFusion ParquetExec(构建于 Rust Parquet 之上)现在是我所知的最复杂的开源 Parquet 读取器。它具有我们能想到的所有用于读取 Parquet 的优化,包括投影下推、谓词下推(行组元数据、页面索引和布隆过滤器)、限制下推、并行读取、交错 I/O 和延迟物化过滤(即将默认启用)。June 最近的一些工作 最近解决了启用延迟物化过滤的剩余障碍,并且 Xiangpeng Hao 正在方便地处理 最后一部分(没有压力😅)。

在没有帮助时跳过部分聚合

许多 ClickBench 查询都是聚合,用于汇总数百万行,这是报告和仪表板的常见任务。DataFusion 使用最先进的 两阶段聚合 计划。通常,两阶段聚合效果良好,因为第一阶段在读取后立即合并许多行,此时数据仍在缓存中。但是,对于某些“高基数”聚合查询(具有大量组),DataFusion 中使用的两阶段聚合策略效率低下,与其他引擎相比,在 ClickBench 查询(例如)中表现出相对较慢的性能

SELECT "WatchID", "ClientIP", COUNT(*) AS c, SUM("IsRefresh"), AVG("ResolutionWidth") 
FROM hits 
GROUP BY "WatchID", "ClientIP" -- **** 13M distinct Groups  ****
ORDER BY c DESC 
LIMIT 10;

对于此类查询,第一个聚合阶段不会显着减少行数,这浪费了大量精力。Eduard Karacharov 通过 动态策略 解决了这个问题,当第一阶段无法有效工作时,可以绕过第一阶段,如图 4 所示。图 4 图 4:来自 DataFusion API 文档 的图表,显示了多阶段分组无效的情况。

优化的多列分组

另一种提高分析数据库性能的方法是针对不同数据类型的操作的专门(又名高度优化)版本,系统在运行时根据查询选择这些版本。与其他系统一样,DataFusion 具有用于处理不同类型的分组列的专用代码。例如,有 专门的代码 用于处理 GROUP BY int_id,以及不同的 专用代码 用于处理 GROUP BY string_id

当查询按多列分组时,应用此技术会比较棘手。例如,GROUP BY string_id, int_idGROUP BY int_id, string_id 具有不同的最佳结构,但不可能为所有可能的分组列类型组合包含专门的版本。

DataFusion 包括 通用的基于行的机制,该机制适用于任何列类型组合,但这种通用机制会将每个值复制两次,如图 5 所示。对于可变长度字符串和二进制数据,这种复制的成本 尤其高昂图 5 图 5:在 DataFusion 43.0.0 之前,具有多个分组列的查询使用基于行的分组存储,并将每个分组值复制两次。对于具有许多不同组的查询(例如 ClickBench 中的几个查询),此复制消耗了大量的查询时间。

数据库中的许多优化可以归结为简单地避免复制,这次也不例外。诀窍在于如何避免复制,同时又不会导致每列比较的开销过大,或者复杂度失控。作为一个勤奋和严谨工程的绝佳例子,Jay Zhan 尝试了 几种 不同的 方法,最终得到了 DataFusion 43.0.0 中发布的版本,如图 6 所示。

图 6 图 6: DataFusion 43.0.0 的新列式分组存储为每个组值精确复制一次,这在按多列分组时速度明显更快。

非常感谢 Emil EjbyfeldtDaniël Heres 对审阅的帮助,以及感谢 Rachelint (kamille) 的审阅和贡献,他贡献了更快的 多组向量化追加和比较,这将在 DataFusion 44 中发布。关于 该工单 的讨论是 DataFusion 社区共同努力构建出色软件的又一个有力例证。

接下来做什么 🚀

正如我期望其他引擎的性能会提高一样,DataFusion 本身也计划进行更多的性能改进

  1. 中间结果阻塞管理(再次感谢 Rachelint Kamille
  2. 默认启用 parquet 过滤器下推 #3463

我们还在讨论 未来三个月 的重点,并且一直在寻找可以提供帮助的人!如果您想与来自世界各地的工程师一起深入探讨(痴迷??)性能和其他功能,我们非常欢迎您加入我们

额外感谢

除了上面提到的人,还要感谢

  1. 感谢 Patrick McGleenon 运行 ClickBench 并收集这些数据 (来源)。
  2. 感谢所有我在致谢中遗漏的人——你们有很多人。我们感谢所有人。

结论

我梦想 DataFusion 登上 ClickBench 排行榜榜首已经好几年了。我经常羡慕那些由大型风险投资、互联网公司或世界一流研究机构支持的系统的改进,并怀疑我们是否可以在时间总是有限的开源项目中完成类似的事情。

我们现在在查询性能方面超越了其他系统这一事实,证明了关注社区并将集体热情和技能朝着共同目标结合起来的力量和可能性。当然,在任何特定基准测试中名列前茅都可能是短暂的,因为其他引擎会改进,但 DataFusion 也会改进!

我喜欢在 DataFusion 上工作——这里的人们、代码的质量、我的互动以及我们共同取得的成果,都远远超出了我的期望以及我的大多数其他软件开发经验。我迫不及待地想看看人们接下来会构建什么,并希望 在网上见到您


  1. 请注意,DuckDB 在“冷”启动时速度稍快。

  2. 想尝试使用自定义格式在 ClickBench 中获得名声/荣耀吗?使用自定义文件格式使 DataFusion 成为 ClickBench 中最快的引擎

  3. 我们的贡献者来自北美、南美、欧洲、亚洲、非洲和澳大利亚。

  4. 本科生、博士、初级工程师和有点古怪的资深工程师。

  5. 感谢 Andy Pavlo,我喜欢这个命名法。