需要更少的镶木地板

时间:2016-08-31 15:57:56

标签: apache-spark dataframe rdd partition bigdata

我正在做以下过程

var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

for (var i = length; i > 0; --i){
    result += ((i & 1) && n.charAt(p) ? '<b>' + n.charAt(p) + '</b>' : chars[Math.floor(Math.random() * chars.length)]);
    if(i & 1) p++;
};

然而,在每个分区下,有太多镶木地板文件和每个分区文件,大小非常小,这将使我的后续步骤变得非常慢,加载所有镶木地板文件。是否有更好的方法在每个分区下,制作更少的镶木地板文件并增加单个拼花文件大小?

5 个答案:

答案 0 :(得分:2)

我曾经遇到过这个问题。

实际上你无法控制文件的分区,因为它取决于执行者在做什么。

解决它的方法是使用方法coalesce进行随机播放,你可以创建你想要的分区数,但是它不是有效的方式你还需要设置足够的驱动程序内存来​​处理这个问题操作。

df = df.coalesce(numPartitions).write.partitionBy(""yyyyy").parquet("xxxx")

答案 1 :(得分:1)

您可以在保存之前重新分区:

rdd.toDF.repartition("Some Column").write.mode(SaveMode.Append).partitionBy("Some Column")

答案 2 :(得分:1)

我也遇到过这个问题。问题是如果你使用coalesce每个分区得到相同数量的镶木地板文件。现在不同的分区有不同的大小,所以理想情况下我需要为每个分区进行不同的合并。

答案 3 :(得分:0)

如果打开很多小文件,它会非常昂贵。我们假设您打开1k文件,每个文件大小远远超出 parquet.block.size 的值。

以下是我的建议:

  • 创建一个作业,该作业将首先合并您的输入镶木地板文件,以使其数量较小的文件的大小接近或等于 parquet.block.size 。 128Mb的默认块大小,但可以通过更新 parquet.block.size 进行配置。如果您的镶木地板文件接近或等于 parquet.block.size 的值,Spark会喜欢。块大小是在内存中缓冲的行组的大小。
  • 或者更新您的火花作业以仅读取有限数量的文件
  • 或者,如果您拥有大型机器和/或资源,只需进行正确的调整即可。

答案 4 :(得分:0)

Hive查询有一种方法可以将小文件合并为更大的文件。这在spark sql中不可用。此外,减少spark.sql.shuffle.partitions不会帮助Dataframe API。 我尝试了下面的解决方案,它产生了较少数量的镶木地板文件(从800个镶木地板文件到29个)。

假设数据已加载到数据帧df

  1. 在配置单元中创建临时表。

    df.createOrReplaceTempView("tempTable")
    spark.sql("CREATE TABLE test_temp LIKE test")
    spark.sql("INSERT INTO TABLE test_temp SELECT * FROM tempTable")
    

    test_temp将包含小的镶木地板文件。

  2. 从临时表中填充最终配置单元

    spark.sql("INSERT INTO test SELECT * FROM test_temp")
    
  3. 最终表格将包含较少的文件。填充决赛桌后删除临时表。