我通过
将拼花数据加载到数据框中spark.read.parquet('hdfs:///path/goes/here/...')
由于镶木地板划分,该路径中有大约50k个文件。当我运行该命令时,spark会产生数十个小工作,整个工作需要几分钟才能完成。以下是火花UI中的工作内容:
正如您所看到的,尽管每个作业都有大约2100个任务,但它们可以在大约2秒钟内快速执行。开始这么多的迷你工作'效率很低,导致此文件列表步骤大约需要10分钟(群集资源大部分处于空闲状态,群集主要处理分散的任务或管理作业/任务的开销)。
如何将这些任务合并到更少的工作中,每个工作都有更多的任务? 解决方案的奖励积分也适用于pyspark。
我在hadoop 2.8.3上通过pyspark运行spark 2.2.1。
答案 0 :(得分:6)
我相信你遇到了一个错误,我的一位前同事已经提交了一张票并开了拉请求。你可以查看here。如果它适合您的问题,那么您最好的投票可能是在问题上投票并在邮件列表上发出一些噪音。
您可能想要做的是调整spark.sql.sources.parallelPartitionDiscovery.threshold
和spark.sql.sources.parallelPartitionDiscovery.parallelism
配置参数(前者在链接的故障单中引用),以适合您的工作。
您可以查看here和here以查看配置密钥的使用方式。为了完整起见,我将在此处分享相关的片段。
spark.sql.sources.parallelPartitionDiscovery.threshold
// Short-circuits parallel listing when serial listing is likely to be faster.
if (paths.size <= sparkSession.sessionState.conf.parallelPartitionDiscoveryThreshold) {
return paths.map { path =>
(path, listLeafFiles(path, hadoopConf, filter, Some(sparkSession)))
}
}
spark.sql.sources.parallelPartitionDiscovery.parallelism
// Set the number of parallelism to prevent following file listing from generating many tasks
// in case of large #defaultParallelism.
val numParallelism = Math.min(paths.size, parallelPartitionDiscoveryParallelism)
此配置的默认值为阈值32
和并行度10000
(相关代码here)。
在你的情况下,我说你可能想要做的就是设置阈值,以便在不产生并行作业的情况下运行该过程。
链接来源来自撰写本文时最新的可用标记版本,2.3.0。
答案 1 :(得分:2)
对于一个对象存储,即使列表和对getFileStatus的调用都非常昂贵,而且这在分区过程中完成,可以大量扩展这个工作。
与mapreduce.input.fileinputformat.list-status.num-threads
一起玩,看看添加更多线程是否会加快速度,比如说值为20-30