Hadoop下将大量小文件生成一个sequenceFile文件

本文探讨了在Hadoop集群环境中使用SequenceFile时常见的问题及解决办法,包括连接配置、文件读取特性以及如何处理.gz文件等内容。

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

1)遇到的问题,因为是在集群上运行,代码中String seqFsUrl = "hdfs://localhost:9000/user/mjiang/target-seq/sdfgz.seq";的localhost错误,

于是老是出现连接不上的问题,(Retrying connect to server: localhost/127.0.0.1:8020. Already tried 0 time(s).)

所以运行程序时出现连接不上Hadoop的问题时,考虑是不是程序写错了。

2)sequenceFile中虽然是按文件名(或其他任何值)为键,文件内容为值来存储的。但用SequenceFileAsTextInputFormat来读取时,键值还是会被读到文件的第一行

没分析源码,不清楚原因

3)sequenceFile可以处理.gz文件(没有实验出不行,按说.gz文件是不可以分块存储的???逻辑上还是一个)

  1. import java.io.BufferedInputStream;  
  2. import java.io.FileInputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.File;  
  6. import java.net.URI;  
  7.   
  8. import org.apache.Hadoop.conf.Configuration;  
  9. import org.apache.Hadoop.fs.FileSystem;  
  10. import org.apache.Hadoop.fs.Path;  
  11. import org.apache.Hadoop.io.IOUtils;  
  12. import org.apache.Hadoop.io.NullWritable;  
  13. import org.apache.Hadoop.io.SequenceFile;  
  14. import org.apache.Hadoop.io.Text;  
  15.   
  16. public class sequeneceFile{  
  17.       
  18.     public static void main(String[] args) throws IOException {  
  19.           
  20.         //String seqFsUrl = "hdfs://localhost:9000/user/mjiang/target-seq/sdfgz.seq";   
  21.         String seqFsUrl = "user/mjiang/target-seq/sdfgz.seq";  
  22.   
  23.         Configuration conf = new Configuration();  
  24.         //conf.set("fs.default.name", "hdfs://venus:9000");   
  25.         //conf.set("Hadoop.job.user", "mjiang");   
  26.         //conf.set("mapred.job.tracker", "venus:9001");   
  27.   
  28.         FileSystem fs = FileSystem.get(URI.create(seqFsUrl),conf);  
  29.   
  30.         Path seqPath = new Path(seqFsUrl);  
  31.   
  32.         //Text key = new Text();   
  33.   
  34.         Text value = new Text();  
  35.   
  36.         String filesPath = "/home/mjiang/java/eclipse/Hadoop/sequenceFile/data/sdfgz/";  
  37.   
  38.         File gzFilesDir = new File(filesPath);  
  39.   
  40.         String[] gzFiles = gzFilesDir.list();  
  41.           
  42.         int filesLen=gzFiles.length;  
  43.           
  44.         SequenceFile.Writer writer = null;  
  45.           
  46.         try {//返回一个SequenceFile.Writer实例 需要数据流和path对象 将数据写入了path对象   
  47.               
  48.                       
  49.             writer = SequenceFile.createWriter(fs, conf, seqPath,NullWritable.class, value.getClass());  
  50.               
  51.             //for (int i=0;i<2;i++){   
  52.                       
  53.             while (filesLen>0){  
  54.               
  55.                 File gzFile = new File(filesPath+gzFiles[filesLen-1]);  
  56.               
  57.                 InputStream in = new BufferedInputStream(new FileInputStream(gzFile));  
  58.               
  59.                 long len = gzFile.length();  
  60.               
  61.                 byte[] buff = new byte[(int)len];     
  62.   
  63.                 if ((len = in.read(buff))!= -1) {  
  64.                   
  65.                     value.set(buff);  
  66.                   
  67.                     writer.append(NullWritable.get(), value);//将每条记录追加到SequenceFile.Writer实例的末尾      
  68.   
  69.                 }  
  70.                   
  71.                 //process   
  72.                   
  73.                 System.out.println(gzFiles[filesLen-1]);  
  74.               
  75.                 //key.clear();   
  76.               
  77.                 value.clear();  
  78.                   
  79.                 IOUtils.closeStream(in);  
  80.                   
  81.                 filesLen--;//!!   
  82.               
  83.             }  
  84.             //filesLen = 2; }   
  85.         } finally {  
  86.   
  87.             IOUtils.closeStream(writer);  
  88.   
  89.         }  
  90.     }  
  91. }  
### Hive 中生成小文件问题的原因 Hive 的小文件问题是由于多种原因造成的。当数据通过不同方式加载到 Hive 表中时,可能会产生许多小于 HDFS 块大小的小文件[^1]。每次执行 `INSERT` 操作时,Hive 至少会产生一个文件,这是因为每个 `INSERT` 操作都会触发 MapTask 或 ReduceTask 来写入数据[^4]。 此外,如果分区较多或者数据量较小的情况下频繁插入数据,则更容易引发小文件问题。这种现象会对 HDFS 元数据造成压力并降低整体查询效率[^2]。 --- ### 解决方案概述 以下是几种常见的方法来缓解或解决 Hive 小文件问题: #### 1. **调整输入参数** 可以通过设置合适的配置项控制任务行为从而减少输出文件数量。例如: - 设置 `mapreduce.job.reduces` 参数指定 Reducer 数目; - 调整 `hive.exec.reducers.bytes.per.reducer` 和其他相关属性优化 reducer 划分逻辑[^3]。 ```bash set mapreduce.job.reduces=10; set hive.exec.reducers.bytes.per.reducer=256MB; ``` 这些操作能够有效合并部分中间结果集进而削减最终产生的物理文件数目。 #### 2. **使用多路合并机制 (Multi-way Merge)** 对于已经存在的众多小文件场景下,可采用 CTAS(Create Table As Select)语句重新构建目标表结构并将源数据按需聚合后再存盘。这种方式利用了 Hive 自带的数据整理能力实现自动化的文件规约过程[^5]: ```sql CREATE TABLE new_table AS SELECT * FROM old_table DISTRIBUTE BY RAND(); ``` 上述 SQL 片段展示了如何借助随机分布函数让原始记录均匀散布至新的分区布局之中,同时达到压缩原有零散碎片的效果。 #### 3. **更改存储格式** 推荐选用更高效的二进制序列化/反序列化框架代替默认文本型编码形式(textfile),比如 Avro, Parquet 或者 ORC 文件格式等。它们具备更高的空间利用率以及内置索引支持特性有助于提升读取速度的同时也能间接抑制不必要的分割倾向. 另外还可以考虑启用 SequenceFile 类型替代传统纯文本模式以期获得更好的兼容性和可控度: ```sql ALTER TABLE your_table SET FILEFORMAT SEQUENCEFILE; ``` 此命令将改变现有表格底层所依赖的具体持久化策略为更加紧凑的形式之一. #### 4. **启用 Hadoop Archive 功能(HAR)** 另一种可行的办法就是依靠 hadoop 提供的归档工具(hadoop archive)把那些孤立无援的小规模单元打包成更大的虚拟集合体来进行统一管理维护工作流. 具体做法如下所示: 先创建档案包再将其挂载回原路径位置即可完成转换流程. ```bash hadoop archive -archiveName my_archive.har -p /source_dir /dest_dir/my_archive.har ``` --- ### 总结 综上所述,针对 Hive 生产环境中不可避免会出现的各种尺寸不均等问题提供了若干种切实有效的应对措施。无论是事前预防还是事后补救都有相应的理论依据和技术手段可供选择实施应用实践验证其价值所在。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值