Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Spark-写入128 MB大小的拼花文件_Scala_Dataframe_Apache Spark_Apache Spark Sql - Fatal编程技术网

Scala Spark-写入128 MB大小的拼花文件

Scala Spark-写入128 MB大小的拼花文件,scala,dataframe,apache-spark,apache-spark-sql,Scala,Dataframe,Apache Spark,Apache Spark Sql,我有一个超过10亿行的数据帧(df) df.coalesce(5) .write .partitionBy("Country", "Date") .mode("append") .parquet(datalake_output_path) 通过上面的命令,我知道在我的100个工作节点集群(spark 2.4.5)中只有5个工作节点将执行所有任务。使用聚结(5)需要7小时才能完成该过程 我应该尝试重新分区而不是合并 是否有一种更快/更有

我有一个超过10亿行的数据帧(df)

df.coalesce(5)
.write
.partitionBy("Country", "Date")
.mode("append")
.parquet(datalake_output_path)
通过上面的命令,我知道在我的100个工作节点集群(spark 2.4.5)中只有5个工作节点将执行所有任务。使用聚结(5)需要7小时才能完成该过程

我应该尝试
重新分区
而不是
合并

是否有一种更快/更有效的方法来写出128 MB大小的拼花地板文件,或者我是否需要首先计算数据帧的大小来确定需要多少个分区

例如,如果我的数据帧大小为1 GB,spark.sql.files.maxPartitionBytes=128MB,我是否应首先计算所需的分区数
为1 GB/128 MB=大约(8)
,然后进行重新分区(8)或合并(8)


这个想法是在编写时最大化输出中拼花文件的大小,并且能够快速(更快地)做到这一点。

如果您从较高的分区数到较低的分区数,则Coalesce会更好。但是,如果在编写df之前,您的代码没有进行洗牌,然后,聚结将被向下推至DAG中可能的最早点。 您可以做的是在100个分区或任何合适的分区中处理df,然后在编写df之前将其持久化。 然后使用coalesce将分区减少到5个,并编写它。这可能会给您带来更好的性能

您可以获得数据帧的大小(
dfSizeDiskMB
df
,方法是将其持久化,然后检查Web UI上的存储选项卡,如下所示。有了这些信息和预期拼花地板压缩比的估计值,您就可以估计达到所需输出文件分区大小所需的分区数,例如

val targetOutputPartitionSizeMB = 128
val parquetCompressionRation = 0.1
val numOutputPartitions = dfSizeDiskMB * parquetCompressionRatio / targetOutputPartitionSizeMB
df.coalesce(numOutputPartitions).write.parquet(path)
请注意,此处不相关,因为它是:

读取文件时要打包到单个分区中的最大字节数

(除非
df
是读取未创建中间数据帧的输入数据源的直接结果。
df
的分区数很可能由
spark.sql.shuffle.partitions
决定,它是spark用于从联接和聚合创建的数据帧的分区数)

我应该尝试重新分区而不是合并吗


coalesce
通常更好,因为它可以避免与
重新分区相关的混乱,但请注意中的警告,即根据您的使用情况,可能会在上游阶段失去并行性。

如果我希望每个分区的拼花文件数最少,您认为这是个好主意吗:-
df.repartition(“国家”,“日期”)。写入。分区方式(“国家”,“日期”)。模式(“附加”)。拼花地板(数据湖输出路径)
Repartition控制内存中的分区,而partitionBy控制磁盘上的分区。我想您应该指定Repartition中的分区数以及控制文件数的列数。在您的情况下,128MB输出文件大小的意义是什么,听起来好像这是您可以容忍的最大文件大小?我只想避免“太多小文件”问题。属性“spark.sql.files.maxPartitionBytes”设置为128MB,因此我希望分区文件尽可能接近128MB。例如,我希望有10个大小为128MB的文件,而不是说大小为20MB的64个文件。我还注意到,即使spark.sql.files.maxPartitionBytes”设置为128MB,我在输出路径中看到了200MB或400MB的文件。我本来希望spark将它们打包到128MB的文件中,但这与另一个问题有关。如果我想在代码中执行此操作,则类似于以下内容
val blockSize=1024*1024*128 sc.hadoopConfiguration.setInt(“dfs.blockSize”,blockSize)sc.hadoopConfiguration.setInt(“parquet.block.size”,blockSize)df.write.option(“parquet.block.size”,128*1024*1024)