PySpark中limit(n).show()与show(n)的性能差异原因问询
Spark 2.4.x 中
limit(n).show()与show(n)性能差异原因分析 核心差异点:两类操作的底层扫描逻辑完全不同
show(n)的默认优化逻辑
Spark原生的show(n)方法底层调用take(n)实现,自带分区提前终止扫描优化:它会优先读取第一个分区的数据,如果第一个分区内的数据量≥n,就会直接终止后续所有分区的扫描任务,仅返回当前取到的n条数据。你的测试场景中第一个分区就包含超过5条有效数据,因此test1仅扫描了单个分区,瞬间返回结果。limit(n).show(n)的版本缺陷(Spark 2.4.x特有)
Spark 2.4版本的CollectLimit物理算子未实现提前终止扫描的优化,逻辑完全不同:- 首先会向所有25个Parquet分区下发扫描任务,要求每个分区返回前5条数据
- 由于你查询的
test_col是Array复杂类型,Parquet扫描的Batched参数为false,不支持批量读取,因此每个分区的扫描任务会读取整个分区的全量数据后再截取前5条,而非读到5条就停止 - 所有分区返回的结果汇总到Driver端后,再全局截取前5条返回
- 2010个任务的来源
Spark 2.4对非批量读取的Parquet文件,会将每个Parquet行组拆分为独立的任务执行,你的50GB文件共包含2010个行组,因此limit(5)触发了全量行组的扫描,单Executor环境下需要串行执行所有任务,耗时极长。
补充说明
该问题属于Spark 2.4.x的已知优化缺失,Spark 3.0及以上版本已经对CollectLimit算子增加了提前终止扫描的逻辑,两类操作的性能会基本一致。
内容的提问来源于stack exchange,提问作者cyclobster
相关产品推荐
相关产品推荐

