Spark SQL合并小文件

一、问题描述

spark.sql.shuffle.partitions=200 spark sql默认shuffle分区是200个,如果数据量比较小时,写hdfs时会产生200个小文件。可通过如下调整,使其自适应的合并小文件(本人测试环境从原来的200个小文件合并成一个文件)

二、解决方案

启用 Adaptive Execution ,从而启用自动设置 Shuffle Reducer 特性

set spark.sql.adaptive.enabled=true;

设置每个 Reducer 读取的目标数据量,其单位是字节。默认64M,一般改成集群块大小

set spark.sql.adaptive.shuffle.targetPostShuffleInputSize=128000000;
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
对于Spark SQL中的小文件问题,可以通过合并文件来解决。以下是OPPO的解决方案,包括具体的实现细节和代码。 1. 使用Hadoop的FileInputFormat和TextInputFormat读取小文件并转换为RDD: ``` val input = sc.newAPIHadoopFile(inputPath, classOf[TextInputFormat], classOf[LongWritable], classOf[Text], sc.hadoopConfiguration) val rdd = input.map(pair => pair._2.toString) ``` 2. 将RDD转换为DataFrame: ``` val schema = StructType(Seq(StructField("line", StringType))) val rowRDD = rdd.map(Row(_)) val df = spark.createDataFrame(rowRDD, schema) ``` 3. 将DataFrame写入临时目录,并设置合并文件的参数: ``` df.write .option("mergeSchema", "true") .option("maxRecordsPerFile", "1000000") .parquet(tempOutputPath) ``` 其中,"mergeSchema"表示是否合并不同文件的schema,"maxRecordsPerFile"表示每个文件包含的最大记录数。 4. 使用Hadoop的FileUtil将临时目录中的小文件合并为一个大文件: ``` val fs = FileSystem.get(sc.hadoopConfiguration) FileUtil.copyMerge(fs, new Path(tempOutputPath), fs, new Path(outputPath), false, sc.hadoopConfiguration, null) ``` 其中,tempOutputPath为临时目录,outputPath为最终输出目录。 完整的代码如下: ``` import org.apache.hadoop.fs.{FileSystem, Path} import org.apache.hadoop.io.{LongWritable, Text} import org.apache.hadoop.mapreduce.lib.input.TextInputFormat import org.apache.spark.sql.{Row, SparkSession} import org.apache.spark.sql.types.{StringType, StructField, StructType} object MergeSmallFiles { def main(args: Array[String]): Unit = { val inputPath = args(0) val outputPath = args(1) val tempOutputPath = outputPath + "/temp" val spark = SparkSession.builder().appName("MergeSmallFiles").getOrCreate() val sc = spark.sparkContext val input = sc.newAPIHadoopFile(inputPath, classOf[TextInputFormat], classOf[LongWritable], classOf[Text], sc.hadoopConfiguration) val rdd = input.map(pair => pair._2.toString) val schema = StructType(Seq(StructField("line", StringType))) val rowRDD = rdd.map(Row(_)) val df = spark.createDataFrame(rowRDD, schema) df.write .option("mergeSchema", "true") .option("maxRecordsPerFile", "1000000") .parquet(tempOutputPath) val fs = FileSystem.get(sc.hadoopConfiguration) FileUtil.copyMerge(fs, new Path(tempOutputPath), fs, new Path(outputPath), false, sc.hadoopConfiguration, null) spark.stop() } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月清风,良宵美酒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值