最近发现离线任务对一个增量Hive表查询越来越慢,推测是由小文件产生的
取HDFS查看确实存在480个小文件

于是合并小文件
insert into test select * from table distribute by floor (rand()*5)
这里采用distribute by进行小文件合并,通过rand()*5,保存从map端输出的文件最多输出到5个reducer,现在只剩下3个文件

小文件合并后同样的查询速度提升非常多。
因为此表格每天有数据进去,增量数据会单独生成一个小文件,日积月累生成大量小文件。小文件对Namenode内存造成压力,对map端文件合并也有很大压力
小文件产生原因
1.动态分区插入数据,会产生大量小文件
2.数据源本来就含有大量小文件
3.数据增量导入,如Sqoop数据导入,增量insert导入数据等
4.分桶表
5.可以修改的表,此种表有一个快照,随时间增加数据越来越大
小文件危害
1.给NameNode内存中fsImage合并造成压力
2.未开启小文件合并,每个文件一个MapTask,集群资源浪费
3.Map端设置小文件合并,单小文件 太多查询缓慢
小文件问题解决
1.Hive参数调节
Hive已经对小文件做了许多优化,只需修改配置文件即可

2.动态分区插入式,保证有静态分区,不要误判产生大量分区
创建分区表
hive (default)> create table dept_partition_dy(id int, name string) partitioned by (loc int) row format delimited fields terminated by '\t';
插入数据
set hive.exec.dynamic.partition.mode = nonstrict;hive (default)> insert into table dept_partition_dy partition(loc) select deptno, dname, loc from dept;
3.按照分区合并导入
如果原表有大量小文件,在导入目标表的时候也会产生大量小文件。如果有分区如dt、hour,可以使用 distribute by dt,hour,
保证每小时数据在一个reduce里面
4.定期合并数据
类似于增量导入数据,会存在小文件,需要进行一天或者一周的定时文件合并
5.覆盖原表数据
insert overwrite table test [partition] select * from table distribute by floor (rand()*5)
将test表中的数据查询出来,在overwrite覆盖表test,不必担心失败数据没有,这里面是有事务保证的。
若是分区表则加上partitiom,标识对分区进行overwrite
6.针对ORC存储的表
ORC格式的表可以使用
alter table test [partition(...)] concatenate
进行小文件合并,这种方法仅适用于ORC格式存储的表
网友评论