SparkStreaming将结果输出到单个文件以及小文件的合并
每个duration批次时间数据量不一定多少,
若数据量太少,
首先每个批次处理数据后会有多个分区的小文件,
解决办法1. 是在结果落地前重分区,每个批次只生成一个文件,
那么要是这一个文件数据量也很小,落地到hive还是会影响查询效率
那么解决办法2. 就用在hive定时执行一个insert overwrite table a select * from a;语句,这个时候会覆盖表的数据达到合并小文件的目的
关于insert overwrite table a select * from a;应该会覆盖原先的文件,不过我还是测试了一下。 在我摘的两篇文章最下面贴截图。
地址是:https://blog.csdn.net/xianpanjia4616/article/details/82888608
sparksql写入hive后小文件太多,影响查询性能的问题
首先我们要知道hive里面文件的数量=executor-coresnum-executorsjob数,所以如果我们batchDuration的设置的比较小的话,每天在一个分区里面就会生成很多的小文件,我们在hive里面查询的时候就会非常的影响性能,下面介绍两种方法优化小文件:
(1),第一种,可以在创建的DataFrame的时候,cache一下,然后对DataFrame进行重新分区,可以把分区设置为1,可以用reparation,当然也可以用coalesce,这两个的区别,可以看我的另外一篇博客,这个时候就会一个job产生一个文件.但是这么做就降低了写入的性能,所以数据量不是特别大的时候,还是可以用的,但是如果数据量很大,就需谨慎使用,
(2),第二种方法是利用sql定时执行一下,insert overwrite table a select * from a;这个时候会覆盖表的数据达到合并小文件的目的,具体的sql下面会有.
下面看一下具体的代码吧:
val df = spark.createDataFrame(rowRDD, schema).cache()
df.coalesce(1).createOrReplaceTempView("tempTable")
val sq = "insert into combine_data partition(day_time='" + day_time + "') select * from tempTable"
sql(sq)
println("插入hive成功了")
df.unpersist(true)
insert overwrite table combine_data partition (day_time='2018-08-01') select data,enter_time from combine_data where day_time = '2018-08-01';
地址:https://www.jianshu.com/p/7e2b20ccc78b
原始的结果
今天终于完成了SparkStreaming的阶段性工作,要将结果数据放入到hdfs上保存,使用的是RDD自己原有的函数saveAsTextFiles(“Path”)
使用函数
结果如下
结果
可以看出,有瑕疵。我是想将我的数据保存在一个文件中,所以有瑕疵。文件太多,文件夹太多。这样的结果对于后面对数据的再次使用,坏处我就不必多说了吧。
可以看出,多文件夹的原因是因为我是使用的SparkStreaming,所以是每个时间段(Duration)执行一次写入的操作,所以会出现多文件夹,并且名字以时间命名。再看文件夹下的多个文件,这是由我的RDD的分区决定的,而RDD的分区是由我指定数量的线程来决定的,因为我是在本地跑的val sparkConf =new SparkConf().setMaster(Constant.SPARK_MASTER_LOCAL),我这里指定的是4,所以是4个文件。对RDD感兴趣的可以去看一下RDD的分区,讲的很好理解,这里就不再赘述。对spark中RDD通俗易懂的介绍
解决方法
思路描述:首先解决多文件的问题,因为文件数量是由分区决定的,那我们就将他重分区,分区数量为1,然后再向hdfs中写入临时目录,写入后我们再将这个文件追加到最终的文件中,然后再把这个临时文件删除。闲话少说,上干货。
解决方法
copyMerge(src.getFileSystem(conf), src, dst)方法如下。
copyMerge(src.getFileSystem(conf), src, dst)
作者:飞叔Brother
链接:https://www.jianshu.com/p/7e2b20ccc78b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
insert overwrite table a select * from a;
创建表 指定数据目录
create table testover(
a int
)
location '/out/18';
覆盖以合并小文件
insert overwrite table testover
select * from testover;