hive处理小文件(进行map、reduce、压缩、归档优化解决)

背景

Hive query将运算好的数据写回hdfs(比如insert into语句),有时候会产生大量的小文件,如果不采用CombineHiveInputFormat就对这些小文件进行操作的话会产生大量的map task,耗费大量集群资源,而且小文件过多会对namenode造成很大压力。所以Hive在正常job执行完之后,会起一个conditional task,来判断是否需要合并小文件,如果满足要求就会另外启动一个map-only job 或者mapred job来完成合并

 

一、    控制hive任务中的map数: 

1.    通常情况下,作业会通过input的目录产生一个或者多个map任务。 

主要的决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改);

2.    举例:假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数。假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块10m,20m,128m,2m),从而产生4个map数。即,如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。

3.    map数越多越好?否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

4.    是不是保证每个map处理接近128m的文件块,就可以了?也不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

解决:减少map数

    假设一个SQL任务:select brand,("hour") time_type,("2018-12-04") times,("05") as hours,("201812") as months,("20181204") as days,count(distinct(openId)) brandCount from log_db.commodlog where create_time like "2018-12-04 05%" and openId !='' group by brand SORT BY brand ASC;

    该任务的inputdir  /user/hive/warehouse/log_db/commodlog/month=201812/day=20181204

    共有194个文件,其中很多是远远小于128m的小文件,总大小9G,正常执行会用194个map任务。

   Map总共消耗的计算资源: SLOTS_MILLIS_MAPS= 623,020

 

通过以下方法来在map执行前合并小文件,减少map数:

启动压缩

set hive.exec.compress.output=true;

set mapreduce.output.fileoutputformat.compress=true; 
set mapreduce.input.fileinputformat.split.maxsize=1073741824;

set mapreduce.input.fileinputformat.split.minsize=1;

set mapreduce.input.fileinputformat.split.minsize.per.node=536870912;

set mapred
<think>好的,我现在需要处理用户关于Hive小文件问题的解决方案的查询。首先,我得回忆一下Hive小文件产生的原因以及常见的解决办法。小文件通常是由于数据写入的过多小量插入操作造成的,比如使用INSERT语句频繁插入少量数据,或者动态分区过多导致每个分区数据量过少。这会影响HDFS的性能,因为每个文件都会占用NameNode的内存,而且处理这些小文件MapReduce任务也会变得低效,因为每个小文件都会启动一个Map任务。 接下来,我需要整理解决方案。常见的解决方式包括合并已有的小文件,调整写入的参数来减少小文件的产生,使用Hive自带的合并工具,或者在数据写入前进行预处理。例如,可以设置合并参数如hive.merge.mapfiles和hive.merge.size.per.task,在写入自动合并小文件。另外,使用Hadoop的Har归档工具也是一种方法,但可能需要额外步骤。还有,分桶表(Bucketing)也可以帮助优化数据存储结构,减少小文件的数量。 需要确保回答的结构清晰,按照用户的要求分点说明,并引用站内的相关资料。例如,用户提供的引用[3]提到分桶表的作用是提高查询效率和抽样,这可以应用到分桶表的解决方案部分。同,引用[2]提到HDFS客户端在并发写入的竞争问题,这可能与调整并发写入参数有关联,比如控制Reducer的数量或者使用合并文件的方法来避免这种情况。 然后,我需要检查是否有遗漏的最佳实践,比如使用Hive的合并命令,或者在ETL过程中进行文件大小的控制。例如,在执行INSERT之前先对数据进行聚合,或者使用ORC格式的文件,因为它们支持更高效的压缩和索引,从而减少文件数量。 还需要考虑Hive on Spark和Hive on Tez等执行引擎的不同配置,可能会影响小文件处理方式。例如,在Spark中调整分区数量或使用coalesce操作来减少输出文件数。 最后,生成相关问题,可能涉及如何监控小文件、不同文件格式的影响,或者分区分桶的最佳实践。这些问题需要自然地从解决方案中延伸出来,帮助用户进一步理解。</think>### Hive处理小文件问题的解决方案及最佳实践 小文件问题在Hive中通常由高频写入、动态分区过多或数据倾斜导致,可能引发HDFS元数据压力增大、查询性能下降等问题[^2]。以下是具体解决方案和最佳实践: --- #### **1. 写入优化** - **调整Reduce数量** 通过控制Reduce任务数量,避免生成过多小文件。例如: ```sql SET hive.exec.reducers.bytes.per.reducer=256000000; -- 每个Reducer处理256MB数据 SET hive.exec.reducers.max=1000; -- 限制最大Reducer数量 ``` - **启用自动合并** 在写入阶段自动合并小文件: ```sql SET hive.merge.mapfiles = true; -- 合并Map输出文件 SET hive.merge.mapredfiles = true; -- 合并Reduce输出文件 SET hive.merge.size.per.task = 256000000; -- 合并后文件目标大小(256MB) SET hive.merge.smallfiles.avgsize = 16000000; -- 当平均文件小于16MB触发合并 ``` --- #### **2. 存储格式与分区设计** - **使用列式存储格式** 如ORC或Parquet,支持更高效压缩和索引,减少文件数量[^3]。 - **合理分区和分桶** - **按间分区**:适用于增量数据分析场景,避免全表扫描。 - **分桶表(Bucketing)**:将数据哈希到固定数量的桶中,既减少小文件又提升查询效率[^3]。 ```sql CREATE TABLE bucketed_table PARTITIONED BY (dt STRING) CLUSTERED BY (user_id) INTO 50 BUCKETS; ``` --- #### **3. 现有小文件处理** - **手动合并文件** 使用`CONCATENATE`命令(仅适用于ORC格式): ```sql ALTER TABLE table_name PARTITION(dt='2023-01-01') CONCATENATE; ``` - **Hadoop Archive(HAR)** 将小文件归档为少量HAR文件: ```bash hadoop archive -archiveName data.har -p /user/hive/warehouse/table /user/archive ``` --- #### **4. 任务级优化** - **调整输入格式** 使用`CombineHiveInputFormat`合并小文件作为输入: ```sql SET hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; ``` - **控制动态分区行为** 限制动态分区数量和写入速度: ```sql SET hive.exec.dynamic.partition.mode=nonstrict; SET hive.exec.max.dynamic.partitions=1000; SET hive.exec.max.dynamic.partitions.pernode=100; ``` --- #### **5. 定期维护与监控** - **自动化清理脚本** 通过定期检查HDFS目录,合并或删除过期小文件。 - **使用Hive ACID特性** 在Hive 3.0+中,事务表支持`COMPACT`命令自动合并增量文件: ```sql ALTER TABLE transactional_table COMPACT 'minor'; ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值