Hadoop 归档 和HIVE 如何使用har 归档 文件

本文深入探讨Hadoop Archive (HAR) 文件的优劣,如何创建、管理和在Hive中使用HAR文件,以及如何通过分区表提升效率。介绍了HAR文件在减少Namenode内存压力方面的优势,同时指出它在MapReduce作业中的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hadoop archive 唯一的优势可能就是将众多的小文件打包成一个har 文件了,那这个文件就会按照dfs.block.size 的大小进行分块,因为hdfs为每个块的元数据大小大约为150个字节,如果众多小文件的存在(什么是小文件内,就是小于dfs.block.size 大小的文件,这样每个文件就是一个block)占用大量的namenode 堆内存空间,打成har 文件可以大大降低namenode 守护节点的内存压力。但对于MapReduce 来说起不到任何作用,因为har文件就相当一个目录,仍然不能讲小文件合并到一个split中去,一个小文件一个split ,任然是低效的,这里要说一点<<hadoop 权威指南 中文版>>对这个翻译有问题,上面说可以分配到一个split中去,但是低效的。
     既然有优势自然也有劣势,这里不说它的不足之处,仅介绍如果使用har 并在hadoop中更好的使用har 文件

首先 看下面的命令
     hadoop archive -archiveName 20131101.har /user/hadoop/login/201301/01 /user/hadoop/login/201301/01
     我用上面的命令就可以将 /user/hadoop/login/201301/01 目录下的文件打包成一个 20131101.har 的归档文件,但是系统不会自动删除源文件,需要手动删除
     hadoop fs -rmr /user/hadoop/login/201301/01/*.*.* 我是用正则表达式来删除的,大家根据自己的需求删除原始文件

 有人说了,我删了,归档文件存在,源文件不在了,如果要恢复怎么办,这个也困惑了我,hadoop 好像确实也没有提供这样的API 可以 还原成源文件
 功夫不负有心人,其实也很简单,直接从har 文件中 cp出来就可以了。

查看har文件:hadoop fs -ls har:////user/heipark/20120108_15.har/
hadoop fs -cp har:////home/hdp-xxx/backup/reportdata/reportdata-20190320.har/20190320  /home/hdp-360osd/backup/reportdata/reportdata-20190320

 

那如何在hive 中使用呢,首先看建表 :
 CREATE EXTERNAL TABLE login_har(
  ldate string,
  ltime string,
  userid int,
  name string)
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY ' '
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://h60:9000/user/hadoop/login/201301/01'
这是正常的文件 建外表 从而可以不损害源文件的情况下 在Hive中查看,外边有啥优点不多说。
如果是har 文件呢?
 CREATE EXTERNAL TABLE login_har(
  ldate string,
  ltime string,
  userid int,
  name string)
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY ' '
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'har:///user/hadoop/login/201301/01/20130101.har'

特别注意:如果是parquet格式等,需要指定

ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'

样例:

CREATE EXTERNAL TABLE tmp_v2(
deviceid String, 
aa string,
bb string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS
  INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
  OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION 'har:///home/xxxx/'

这样就可以实现,但这样不好,为什么不好呢,我只能制定单一的目录,假如我的数据增加了,如何能动态的修改呢?

其实也简单,可以使用分区表的形式:
 CREATE EXTERNAL TABLE login_har(
  ldate string,
  ltime string,
  userid int,
  name string)
PARTITIONED BY (
  ym string,
  d string)
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY ' '
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://h60:9000/user/hadoop/login'

先对其父目录建表,然后对年月日进行分区PARTITIONED BY 即是进行分区
再手动修改 其动态分区 即可:
     alter table login_har add partition(ym='201301',d='01') LOCATION 'har:///flume/loginlog/201301/01/20130101.har';
标注为红色的 实践中证明 只能 支持select * from 不加条件的查询,意思就是如果hive mapreduce的话,那就无法 通过这种方式
 alter table login_har add partition(ym='201301',d='01') LOCATION 'hdfs://h60:9000/flume/loginlog/201301/01/20130101.har'; 
只能通过下面的方式进行。

这样不是很好,既可以对hive 表进行分区索引,也可以动态增加har 文件 到新的分区中。har包不能一旦建成不能修改,我们可以打小包,建目录的方式进行分而治之,既满足需求也不影响效率。
--------------------- 
作者:Mr-zhou 
来源:优快云 
原文:https://blog.youkuaiyun.com/zhouleilei/article/details/18414001?utm_source=copy 

 

 

================================================================================================

 

har命令说明

  1.   参数“-p”为src path的前缀
  2.   src可以写多个path

 

archive -archiveName NAME -p <parent path> <src>* <dest>

生成HAR文件

  • 单个src文件夹:

 

hadoop archive -archiveName 419.har -p /fc/src/20120116/ 419 /user/heipark

  • 多个src文件夹

hadoop archive -archiveName combine.har -p /fc/src/20120116/ 419 512 334 /user/heipark

  • 不指定src path,直接归档parent path(本例为“ /fc/src/20120116/ ”, “ /user/heipark ”仍然为输出path),这招是从源码里翻出来的,嘿嘿。

hadoop archive -archiveName combine.har -p /fc/src/20120116/ /user/heipark

 

  •  使用模式匹配的src path,下面的示例归档10、11、12月文件夹的数据。这招也是从源码发出来的。

hadoop archive -archiveName combine.har -p /fc/src/2011 1[0-2] /user/heipark

 

查看HAR文件

hadoop fs -ls har:////user/heipark/20120108_15.har/
#输出如下:
drw-r--r-- - hdfs hadoop 0 2012-01-17 16:30 /user/heipark/20120108_15.har/2025
drw-r--r-- - hdfs hadoop 0 2012-01-17 16:30 /user/heipark/20120108_15.har/2029

 

 

#使用hdfs文件系统查看har文件
hadoop fs -ls /user/yue.zhang/20120108_15.har/ 
#输出如下:
-rw-r--r-- 2 hdfs hadoop 0 2012-01-17 16:30 /user/heipark/20120108_15.har/_SUCCESS
-rw-r--r-- 5 hdfs hadoop 2411 2012-01-17 16:30 /user/heipark/20120108_15.har/_index
-rw-r--r-- 5 hdfs hadoop 24 2012-01-17 16:30 /user/heipark/20120108_15.har/_masterindex
-rw-r--r-- 2 hdfs hadoop 191963 2012-01-17 16:30 /user/heipark/20120108_15.har/part-0

 

Har Java API (HarFileSystem )

 

Java代码 

  1. public static void main(String[] args) throws Exception {  
  2.     Configuration conf = new Configuration();  
  3.     conf.set("fs.default.name", "hdfs://xxx.xxx.xxx.xxx:9000");  
  4.           
  5.     HarFileSystem fs = new HarFileSystem();  
  6.     fs.initialize(new URI("har:///user/heipark/20120108_15.har"), conf);  
  7.     FileStatus[] listStatus = fs.listStatus(new Path("sub_dir"));  
  8.     for (FileStatus fileStatus : listStatus) {  
  9.         System.out.println(fileStatus.getPath().toString());  
  10.     }  
  11. }  

 

代码详细讲解:https://wenku.baidu.com/view/5a6e70efb8f67c1cfad6b888

 

 

<think>好的,我现在需要处理用户关于Hive中小文件问题的解决方案的查询。首先,我得回忆一下Hive中小文件产生的原因以及常见的解决办法。小文件通常是由于数据写入时的过多小量插入操作造成的,比如使用INSERT语句频繁插入少量数据,或者动态分区过多导致每个分区数据量过少。这会影响HDFS的性能,因为每个文件都会占用NameNode的内存,而且处理这些小文件时,MapReduce任务也会变得低效,因为每个小文件都会启动一个Map任务。 接下来,我需要整理解决方案。常见的解决方式包括合并已有的小文件,调整写入时的参数来减少小文件的产生,使用Hive自带的合并工具,或者在数据写入前进行预处理。例如,可以设置合并参数如hive.merge.mapfileshive.merge.size.per.task,在写入时自动合并小文件。另外,使用HadoopHar归档工具也是一种方法,但可能需要额外步骤。还有,分桶表(Bucketing)也可以帮助优化数据存储结构,减少小文件的数量。 需要确保回答的结构清晰,按照用户的要求分点说明,并引用站内的相关资料。例如,用户提供的引用[3]提到分桶表的作用是提高查询效率抽样,这可以应用到分桶表的解决方案部分。同时,引用[2]提到HDFS客户端在并发写入时的竞争问题,这可能与调整并发写入参数有关联,比如控制Reducer的数量或者使用合并文件的方法来避免这种情况。 然后,我需要检查是否有遗漏的最佳实践,比如使用Hive的合并命令,或者在ETL过程中进行文件大小的控制。例如,在执行INSERT之前先对数据进行聚合,或者使用ORC格式的文件,因为它们支持更高效的压缩索引,从而减少文件数量。 还需要考虑Hive on SparkHive 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 ArchiveHAR)** 将小文件归档为少量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、付费专栏及课程。

余额充值