返回博客

更新的 PDS-H 基准测试结果(2025 年 5 月)

2025 年 6 月 1 日,星期六

距离我们上次发布基准测试结果已经有一段时间了。从那时起,我们在优化查询引擎方面付出了大量努力,而其他数据框库(如 pandas)也取得了巨大进步。是时候看看我们的表现了!

PDS-H 基准测试

Polars 决策支持(PDS)基准测试源自 TPC-H 基准测试,因此使用 PDS 获得的任何结果都不能与已发布的 TPC-H 基准测试结果进行比较,因为使用 PDS 获得的结果不符合 TPC-H 基准测试的规定。

原始的 TPC-H 基准测试是一个决策支持基准测试。它包含一种标准化方式来生成各种规模的数据,以及一组要运行的 SQL 查询。

通过比较各种引擎在每个查询上的性能,很容易看出每个引擎的优点和缺点。

为 DataFrame 前端进行调整

原始的 TPC-H 基准测试旨在用于 SQL 数据库,不允许修改 SQL 查询。我们正试图对 SQL 前端和 DataFrame 前端都进行基准测试,因此原始规则必须稍作修改。我们认为 SQL 查询应语义化地转换为宿主工具的惯用查询。为此,我们遵循以下规则:

  • 不允许插入新操作,例如,在连接之前不能剪枝表。
  • 每个解决方案必须为每个问题提供一个查询,独立于数据源。
  • 解决方案必须调用其自身的 API。
  • 允许声明连接类型,因为这符合 DataFrame API 中的语义推理。
  • 一个解决方案必须为所有查询选择一个单一的引擎/模式。允许同一供应商提出不同的解决方案,例如 (spark-sql, pyspark, polars-sql, polars-default, polars-streaming)。但是,这些解决方案应该运行所有查询,以展示其优点和缺点。不允许挑肥拣瘦。
  • 连接不能手动重新排序。

设置

我们实现的基准测试是开源的,可在 GitHub 上获取

我们对以下库的最新版本进行了基准测试:

以下配置与各种库相关:

  • 对于 PySpark,驱动程序内存和执行器内存分别设置为 100g100g
  • 对于 Dask,使用了 threads 调度器。
  • 对于 pandas/Dask/Modin,启用了 PyArrow 数据类型。
  • 对于 pandas,启用了写时复制(copy-on-write)。

请注意,我们不再包含以下 DataFrame 库:

  • vaex,因为它不再维护。
  • Modin,我们很难获得比 pandas 更好的结果。

请注意,并非所有查询都为所有库实现了。这是一个持续进行的过程,欢迎提交 PR

通用硬件/软件

所有查询均在以下条件下运行:

  • 机器:AWS c7a.24xlarge (96 vCPU / 192 GB 内存)
  • 操作系统:Ubuntu 22.02 LTS x86-64

规模因子

PDS-H 允许在不同数据量下运行查询。我们在规模因子 10 和规模因子 100 下进行了运行,其中 1 单位规模因子大致相当于 1GB 的 CSV 数据。在 SF-10 上表现不佳的工具被排除在 SF-100 运行之外,因为它们的性能问题在更高的规模因子下只会恶化。

结果

下方是显示每个查询执行时间(以秒为单位)的条形图,条形越短表示性能越好。对于 SF-10 和 SF-100,Polars 和 DuckDB 都证明是独一档的,比 Dask 和 PySpark 快一个数量级。Pandas 仅在 SF-10 基准测试中运行,因为它的单线程执行和缺乏查询优化器导致两个数量级的差异,并在更高的规模因子下出现内存不足(OOM)失败。

SF-10

pdsh_benchmark_sf-10 pdsh_benchmark_sf-10

解决方案 总时间 因子
polars[streaming]-1.30.0 3.89 1.0
duckdb-1.3.0 5.87 1.5
polars[in-memory]-1.30.0 9.68 2.5
dask-2025.5.1 46.02 11.8
pyspark-4.0.0 120.11 30.9
pandas-2.2.3 365.71 94.0

SF-100

一旦我们扩展到 SF-100,我们会发现 Polars 的内存中引擎相对于其他解决方案来说会慢很多。这主要是由于 CPU 缓存未命中。由于内存中引擎处理内存中的所有数据,我们受到了内存限制。我们发现 Polars 流式引擎不受这些影响。此外,流式引擎还具有更好的核心利用率。Polars 的流式引擎和 DuckDB 再次获得了相似的结果。Polars 在查询 21 中落后。查询 21 具有范围连接(range join),我们尚未在流式引擎中实现。对于此查询,我们(在获得流式支持之前)会回退到内存中引擎进行范围连接。

pdsh_benchmark_sf-10 pdsh_benchmark_sf-10

解决方案 总时间 因子
duckdb-1.3.0 19.65 1.0
polars[streaming]-1.30.0 23.94 1.2
polars[in-memory]-1.30.0 152.27 7.7
pyspark-4.0.0 312.43 15.9
dask-2025.5.1 548.52 27.9

总结

基准测试显示了我们通过新的流式引擎所取得的巨大飞跃。与内存中引擎相比,这表明 Polars 流式引擎可以快达 3-7 倍。当然,您的实际效果会因用例和硬件而异。要从我们最新的改进中受益,请在项目开始时通过设置 pl.Config.set_engine_affinity(engine="streaming") 来选择使用新的流式引擎。我们预计流式引擎将在今年晚些时候成为 Polars lazy 的默认引擎。

1
2
4
3
5
6
7
8
9
10
11
12