Pyspark中的Limit(n)与Show(n)性能差异



试图更深入地了解spark是如何工作的,并尝试使用pyspark-cli(2.4.0(。我正在寻找使用limit(n).show()show(n)之间的区别。对于两个非常相似的查询,我得到了两个非常不同的性能时间。以下是我运行的命令。下面代码中引用的拼花地板文件大约有50列,在远程HDFS上的大小超过50gb。

# Create dataframe
>>> df = sqlContext.read.parquet('hdfs://hdfs.host/path/to.parquet') ↵
# Create test1 dataframe
>>> test1 = df.select('test_col') ↵
>>> test1.schema ↵
StructType(List(StructField(test_col,ArrayType(LongType,true),true)))
>>> test1.explain() ↵
== Physical Plan ==
*(1) Project [test_col#40]
+- *(1) FileScan parquet [test_col#40]
Batched: false,
Format: Parquet,
Location: InMemoryFileIndex[hdfs://hdfs.host/path/to.parquet],
PartitionCount: 25,
PartitionFilters: [],
PushedFilters: [],
ReadSchema: struct<test_col:array<bigint>>
# Create test2 dataframe
>>> test2 = df.select('test_col').limit(5) ↵
>>> test2.schema ↵
StructType(List(StructField(test_col,ArrayType(LongType,true),true)))
>>> test2.explain() ↵
== Physical Plan ==
CollectLimit 5
+- *(1) Project [test_col#40]
+- *(1) FileScan parquet [test_col#40]
Batched: false,
Format: Parquet,
Location: InMemoryFileIndex[hdfs://hdfs.host/path/to.parquet],
PartitionCount: 25,
PartitionFilters: [],
PushedFilters: [],
ReadSchema: struct<test_col:array<bigint>>

请注意,test1test2的物理计划几乎相同。唯一的例外是test2的计划以";CollectLimit 5";。设置之后,我运行了test1.show(5)test2.show(5)。测试1立即返回结果。测试2显示了一个进度条,包含2010项任务,大约需要20分钟才能完成(我只有一个执行者(

问题为什么测试2(有限制(与测试1(无限制(相比表现如此糟糕?数据集和结果集完全相同,物理计划几乎完全相同。

请记住:

  • show()show(20)的别名,在内部依赖于take(n: Int): Array[T]
  • limit(n: Int)返回另一个数据集,并且是读取整个源的昂贵操作

限制-导致新的数据帧并花费更长的时间,因为这是因为当前输入文件格式不支持谓词下推。因此读取整个数据集并应用限制。

最新更新