News Hacker|极客洞察

🤔650GB Delta Lake(S3)基准:Polars / DuckDB / Daft / Spark 的单机性能与 IO 瓶颈争议
靠 650GB 基准就敢否认集群必要性?

🎯 讨论背景

原文是对放在 S3 上的约 650GB Delta Lake(Parquet)数据,在单机环境下用 Polars、DuckDB、Daft 与 Spark 执行简单按时间戳计数聚合的对比基准。测试在 AWS 实例(作者使用 c5.4xlarge,约 10Gbps)上运行,引发社区对基准代表性、S3/网络带宽是否主导结果、以及列式存储(Parquet)和目录层(Delta Lake/delta-rs/DuckLake)对实际扫描量的影响的激烈讨论。评论既有赞扬单机现代引擎在多数中等规模场景下的易用性与性能,也有强调并发、治理和 PB 级数据下分布式或托管服务不可替代的观点,还深入讨论了元数据、删除向量、小文件与实例选择等细节性权衡。

📌 讨论焦点

单节点现代引擎在中等规模分析中的可行性

多位评论者指出现代单机分析引擎(如 DuckDB、Polars、ClickHouse、Daft)在多数中等规模数据场景下表现极佳且更易上手。实际经验里有人把数百 GB 到 TB 级的查询交给 DuckDB 或 ClickHouse,结果比使用 Flink、PySpark、Dask、Ray 更省事且速度接近最佳,DuckDB 被描述为“几乎开箱即用”。Daft 团队也在评论中回应会优化其 deltalake reader 的并行性与 groupby 的流水线能力,说明这些单机引擎仍在快速演进。因开发与调试分布式作业成本高,不少人建议先用 DuckDB/ClickHouse 作为起点再决定是否上分布式集群。

[来源1] [来源2] [来源3] [来源4]

基准被 I/O 与实例网络带宽主导的批评

大量评论认为此次基准的时间很可能被 S3 读取与云实例网络带宽(NIC)主导,而非引擎计算差异。示例指出作者使用的是 c5.4xlarge(峰值约 10Gbps),在理论持续满载下从 S3 拉取 650GB 约需 ~9 分钟,所以文件拉取并发、S3 对象吞吐、解压(如 snappy)等会主导整体耗时。评论进一步提醒本地 NVMe、或高带宽实例(如 c6n/m6n、c8gn 等 100Gbps+)在同样工作负载下可显著胜出,且单一对象的 byte-range 读取、对象并行度与小文件分布会极大影响测得结果。由此推论,实例型号、I/O 策略与数据布局往往比微小的引擎优化更能决定基准排名。

[来源1] [来源2] [来源3] [来源4] [来源5]

分布式系统仍有必要的业务与并发理由

不少评论强调即便单机在单次批处理上表现好,分布式系统在并发用户、低尾延迟、多阶段任务与企业治理上仍不可或缺。分布式集群能把内存与网络聚合用于复杂多阶段 shuffle、并发查询以缩短多人等待时间;托管方案(如 Snowflake、Databricks)能快速提供弹性、权限与审计等企业级功能,降低运维门槛。组织层面的考量(风险分散、外包、现成生态與管理支持)常常使团队宁可接受更高成本也不愿自建轻量化方案。对于数百 TB 到 PB 级别的长期分析或需要大量并发的场景,评论者也建议依然需要专门的分布式或短时爆发式查询 fleet。

[来源1] [来源2] [来源3] [来源4] [来源5]

基准设计与查询类型不具代表性(单列聚合、列修剪与压缩影响)

大量反对意见集中在基准只做了一个按时间戳计数的单列聚合,这类查询会触发 Parquet 的列修剪,从而实际读取的数据远小于文件总量。评论指出 Parquet 是列式且按页/row-group 存储,加上压缩,测试中“650GB 的 Parquet”在读取单列时可能只有几 GB 被解压并处理,因此无法代表典型多列、join、排序或跨阶段管道的复杂查询。有人要求看到超出内存、真实多阶段或有大量中间数据的测试才可推广结论;并批评用 ~40 列的模拟数据只测试单列会产生误导性结果。

[来源1] [来源2] [来源3] [来源4]

数据格式与目录层的权衡(Delta Lake、delta-rs、DuckLake、删除向量)

讨论深入到 Delta Lake 生态与目录设计的细节:Polars 对 Delta Lake 的支持依赖于 delta-rs,而 delta-rs 当前不完全支持 deletion vectors,这会影响带有删除或版本化历史的数据读取正确性。DuckLake 被建议作为 DuckDB 的 catalog/格式方案,但它要求把元数据存到 RDBMS(带来 ACID 优势),这对于想要“只有 Parquet 文件即可自举”的用户被视为额外复杂度与一类设计权衡。评论也提到小写入内联(inlining)与回写 Parquet 的功能仍在迭代、Iceberg 等替代目录的文件式实现会在并发与锁设计上有不同权衡,这些元数据层面的设计会直接影响可运维性和查询语义,而非仅靠引擎性能决定选择。

[来源1] [来源2] [来源3] [来源4] [来源5]

命令行工具的争议与生产力/成本权衡

有人提出用 GNU 工具(如 awk)处理“650GB 也不算大”,但多位评论者反驳称现代分析引擎在并行化、流水线处理与解析复杂格式(大量 JSON 或 Parquet)时更易接近最大性能。旧文宣称命令行工具很快,但实践证明在 JSON-heavy 或需要高并行度的聚合上用纯 CLI 很难达到像 ClickHouse 或 DuckDB 那样的便利和性能。更重要的是工程成本、调试与运维开销:写分布式作业或维护集群会带来隐性成本,有时选择简单的单机工具能显著提高生产力并降低总成本。

[来源1] [来源2] [来源3] [来源4] [来源5]

📚 术语解释

Delta Lake: Delta Lake:由 Databricks 推广的开源事务性数据湖层,用于在对象存储(如 S3)上提供 ACID 元数据、版本控制与时间旅行等特性,常见于 lakehouse 架构中。

delta-rs: delta-rs:针对 Delta Lake 的 Rust 实现与客户端库,被多种单机工具用来读取/写入 Delta Lake;评论中提到它当前对 deletion vectors 的支持不足,影响某些版本化/删除场景。

DuckLake: DuckLake:DuckDB 社区提出的一种 catalog/目录方案,用关系型数据库保存元数据以提供 ACID 语义和小写入内联(inlining)功能;设计权衡包括必须依赖 RDBMS 与回写 Parquet 的实现细节。

Parquet: Parquet:列式压缩存储格式(columnar),按列/页/row-group 存储数据,支持列修剪(只读取查询所需列)和高效压缩,这些机制显著影响 I/O、内存和解压开销。

Deletion vectors: Deletion vectors:一种在 Delta Lake 等系统中用于标记已删除行的机制(类似行级过滤元数据),读取端必须支持该机制才能正确排除已删除的数据快照。

Column pruning(列修剪): Column pruning:查询优化技术,利用列式存储只读取查询需要的列,从而减少 I/O 与解压工作量;在基准里单列聚合会显著降低实际读取的数据量。