小文件问题

1 影响

  • hdfs设计目的就不是为了存储小文件,而是高吞的文件系统,如果小文件过多会导致nn的元数据信息太多,会导致nn的内存吃紧
  • 处理文件的时候,小文件特别小,但是打开时间却要很久,读取元数据信息的时间需要很久,会造成资源浪费,nn访问文件需要不断的寻址
  • 小文件的计算成本也会很高,引擎原因可能会开启多个map

2 产生

说到小文件那就得说说小文件怎么来的,什么操作会产生小文件,hdfs内的小文件产生的原因,我个人总结了以下三点

2.1 insert ino直接向表中插入数据,

  • 如果是分区表,有目标分区,就追加,不会产生小文件.但是如果分区表无目标分区就会产生新的文件,甚至是小文件
  • 如果是非分区表,那就直接追加到文件末尾不会产生小文件
  • 但是以上两点都受制于几个hive的小文件合并参数,有可能每次都会新增新的小文件

2.2 load加载数据

  • hive load数据有两种形式,一种覆写一种插入
  • 这一点也会受制于几个hive的小文件合并参数,可能每次都会新增新的小文件

2.3 日常的select查询插入

2.3.1 不说tez

2.3.2 hive

2.3.2.1 没有shuffle
insert into table tmp.tbname values ('col1_value', 1),('col1_value', 2);

$ hadoop fs -ls /user/hive/warehouse/tmp.db/tbname/day=2018-12-12      
Found 2 items
-rwxrwxrwx   3 hadoop supergroup         26 2019-12-20 15:56 hdfs://sdg/user/hive/warehouse/ttmpdb/tbname/day=2018-12-12/000000_0

--结论:一个单独的插入语句会启动一个mr任务,回生成一个对应的结果文件
2.3.2.2 有shuffle
hive> insert into table tmp.czc_hive_game select count(*), game_id from ttmpsource_table group by game_id;


Hadoop job information for Stage-1: number of mappers: 62; number of reducers: 1

--结论:groupby的时候按照key字段进行shuffle, 最后启动了62个map和一个reduce,最后由reduce聚合输出,所以只有一个
2.3.2.3 hive如何决定写文件的个数

reduce个数决定任务的最终效果,不单独设置的情况下,hive会默认生成一个reduce

相关参数是

hive.exec.reducers.bytes.per.reducer
-- reduce处理数据量大小,默认1g

hive.exec.reducers.max
--reduce接受的数据量的参数,那么只会有一个reduce任务;

2.3.3 spark

2.3.3.2 没有shuffle
spark.sql("insert into table tmp.czc_spark_test_write values ('col1_value', 1),('col1_value', 2)")

$ hadoop fs -ls  /user/hive/warehouse/ttmpdb/czc_spark_test_write
Found 2 items
-rwxrwxrwx   3 hadoop supergroup         13 2019-12-20 17:01 /user/hive/warehouse/tetmpb/czc_spark_test_write/part-00000-0db5ce49-fb85-4c15-bac8-fa2213a03203-c000
-rwxrwxrwx   3 hadoop supergroup         13 2019-12-20 17:01 /user/hive/warehouse/temtmp/czc_spark_test_write/part-00001-0db5ce49-fb85-4c15-bac8-fa2213a03203-c000

$ hadoop fs -cat /user/hive/warehouse/temptmpczc_spark_test_write/part-00000-0db5ce49-fb85-4c15-bac8-fa2213a03203-c000
col1_value      1

$ hadoop fs -cat /user/hive/warehouse/temp.tmpzc_spark_test_write/part-00001-0db5ce49-fb85-4c15-bac8-fa2213a03203-c000
col1_value      2

--结论:就算是一个简单的插入语句也会启动两个并行分区并产生两个文件
2.3.3.3 有shuffle
scala>  spark.sql("insert into table tmp.tbname select count(*), game_id from ttmpsource_table  group by game_id");
res1: org.apache.spark.sql.DataFrame = []

hive> select count(distinct game_id) from tetmpource_table;
OK
26

$ hadoop fs -ls hdfs://sdg/user/hive/warehouse/temtmp/tbname
Found 26 items
-rwxrwxrwx   3 hadoop supergroup          0 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temptmptbname/part-00000-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup          8 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temp.tmpzc_spark_game/part-00007-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup          7 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temp.dtmpc_spark_game/part-00010-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup          9 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temp.dbtmp_spark_game/part-00011-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup          9 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temp.db/tmpspark_game/part-00012-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup          9 2019-12-20 14:46 hdfs://sdg/user/hive/warehouse/temp.db/ctmppark_game/part-00032-2f2213b2-a5b7-4c20-83da-dd25c4b018b9-c000
-rwxrwxrwx   3 hadoop supergroup         14 2019-12-20 14:46 
.........

--结论:每个key一个shuffle分区,一共26个文件
2.3.3.3 spark的文件数量

不是由spark框架直接决定的,而是由输入数据的文件系统或存储系统决定的,spark读取文件来获取数据,然后分布式运行,一般都是按照文件的个数直接决定分区数, 每个文件被视为一个输入分区,所以如果希望增加这里的并行可以试试orc相关的读参数或者是map的split参数,或者是pyspark的一些支持分区的算子

2.4 动态分区

动态分区如果没有事现调配好分区参数,也会产生很多小文件,甚至溢出执行引擎

3 避免/处理

3.1 hive/mr

--调整map参数

	--map合并小文件
	--map输出和reduce输入
	--控制在数据加载和查询过程中是否合并MapReduce任务的输出文件
	hive.merge.mapfiles
	hive.merge.smallfiles.avgsize
	
--调整reduce参数
	
	--每个reduce任务处理的数据量,默认1g
	hive.exec.reducers.bytes.per.reducer
	--如果reduce的输入, 也就是map的输出,大小不超过1g,就只会有一个reduce
	hive.exec.reducers.max
	
--调整mr参数
	 mapred.max.split.size
	 mapreduce.job.reduces

3.2 spark

有些网上的参数可以适用

-- 动态规划shuffle的过程
-- 并不是所有版本的hive通用,可以用set测试一下
set spark.sql.adaptive.enabled=true 


-- 这些需要调配
spark.sql.shuffle.partitions;
set spark.yarn.driver.memory=16g;
set spark.executor.memory=8g;
set spark.executor.instances=256;
set spark.executor.cores=6;

--sparksql还可以搭配di's't'ru'b

3.3 hdfs

  • 如果是orc优先使用lzo压缩
  • 直接用concatenate快速合并
  • ALTER TABLE/PARTITION XXX CONCATENATE;hive自带的合并文件的命令
  • 使用hadoop命令archive
    • 先进行unarchive

3.4 其他

  • 情况有时候是多重复杂的,可以配置crontab脚本定期进行小文件合并操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值