用于文件写入的Spark分区非常慢

时间:2016-04-01 09:52:05

标签: hadoop apache-spark hdfs parquet hadoop-partitioning

使用Spark将文件写入HDFS时,不使用分区时速度非常快。而不是那样,当我使用分区来写入文件时,写入延迟增加了因子〜24。

对于同一文件,无分区写入大约需要600毫秒。使用Id编写分区(将生成正好1.000个分区,因为文件中有1.000个ID),大约需要14秒。

你们中的一些人是否有同样的经历,写一个分区文件需要很长时间?造成这种情况的根本原因可能是Spark需要为每个分区创建1.000个文件夹和文件? 你知道如何加快它的速度吗?

val myRdd = streamedRdd.map { case ((id, metric, time), value) => Record(id, metric, getEpoch(time), time, value) }

val df = myRdd.toDF

df.write.mode(SaveMode.Append)
.partitionBy("id")
.parquet(path)

1 个答案:

答案 0 :(得分:1)

Spark执行程序与HDFS通信以写入它们拥有的数据,这取决于分区后数据在群集中的传播方式。

显然,对于较小的数据块,与顺序写入整个文件相比,建立从多个执行器节点到HDFS和写入的连接的时间会更多。

如何避免这种情况:

默认情况下,spark使用Hash分区程序对数据进行分区(哈希键和具有相同哈希值的键转到同一节点)尝试指定范围分区程序,请在下面找到示例代码段:

以下代码段使用哈希分区程序     yourRdd.groupByKey()。saveAsTextFile(" HDFS PATH");

以下代码段使用我们的自定义范围分区程序 它创建了RangePartitioner(8, yourRdd)中提到的8个分区,通过8个连接写入将是更好的选择,然后写入1000个连接。

val tunedPartitioner = new RangePartitioner(8, yourRdd)
val partitioned = yourRdd.partitionBy(tunedPartitioner).saveAsTextFile("HDFS PATH");

同样,这是要写入的数据与您创建的分区数量之间的权衡。