`

基于 Hive 的文件格式:RCFile 简介及其应用

阅读更多

Hadoop 作为MR 的开源实现,一直以动态运行解析文件格式并获得比MPP数据库快上几倍的装载速度为优势。不过,MPP数据库社区也一直批评Hadoop由于文件格式并非为特定目的而建,因此序列化和反序列化的成本过高。

1、hadoop 文件格 式简介

目前 hadoop 中流行的文件格式有如下几种:

(1 ) Seque nceFile

SequenceFile是Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。这种二进制文件内部使用Hadoop 的标准的Writable 接口实现序列化和反序列化。它与Hadoop API中的MapFile 是互相兼容的。Hive 中的SequenceFile 继承自Hadoop API 的SequenceFile,不过它的key为空,使用value 存放实际的值, 这样是为了避免MR 在运行map 阶段的排序过程。如果你用Java API 编写SequenceFile,并让Hive 读取的话,请确保使用value字段存放数据,否则你需要自定义读取这种SequenceFile 的InputFormat class 和OutputFormat class。

(2) RCFile

RCFile是Hive推出的一种专门面向列的数据格式。 它遵循“先按列划分,再垂直划分”的设计理念。当查询过程中,针对它并不关心的列时,它会在IO上跳过这些列。需要说明的是,RCFile在map阶段从远端拷贝仍然是拷贝整个数据块,并且拷贝到本地目录后RCFile并不是真正直接跳过不需要的列,并跳到需要读取的列, 而是通过扫描每一个row group的头部定义来实现的,但是在整个HDFS Block 级别的头部并没有定义每个列从哪个row group起始到哪个row group结束。所以在读取所有列的情况下,RCFile的性能反而没有SequenceFile高。

HDFS块内行存储的例子

HDFS块内列存储的例子

 

HDFS块内RCFile方式存储的例子

 

(3) Av ro

Avro是一种用于支持数据密集型的二进制文件格式。它的文件格式更为紧凑,若要读取大量数据时,Avro能够提供更好的序列化和反序列化性能。并且Avro数据文件天生是带Schema定义的,所以它不需要开发者在API 级别实现自己的Writable对象。最近多个Hadoop 子项目都支持Avro 数据格式,如Pig 、Hive、Flume、Sqoop和Hcatalog。

(4) 文本格式

除上面提到的3种二进制格式之外,文本格式的数据也是Hadoop中经常碰到的。如TextFile 、XML和JSON。 文本格式除了会占用更多磁盘资源外,对它的解析开销一般会比二进制格式高几十倍以上,尤其是XML 和JSON,它们的解析开销比Textfile 还要大,因此强烈不建议在生产系统中使用这些格式进行储存。 如果需要输出这些格式,请在客户端做相应的转换操作。 文本格式经常会用于日志收集,数据库导入,Hive默认配置也是使用文本格式,而且常常容易忘了压缩,所以请确保使用了正确的格式。另外文本格式的一个缺点是它不具备类型和模式,比如销售金额、利润这类数值数据或者日期时间类型的数据,如果使用文本格式保存,由于它们本身的字符串类型的长短不一,或者含有负数,导致MR没有办法排序,所以往往需要将它们预处理成含有模式的二进制格式,这又导致了不必要的预处理步骤的开销和储存资源的浪费。

(5) 外部格式

Hadoop实际上支持任意文件格式,只要能够实现对应的RecordWriter和RecordReader即可。其中数据库格式也是会经常储存在Hadoop中,比如Hbase,Mysql,Cassandra,MongoDB。 这些格式一般是为了避免大量的数据移动和快速装载的需求而用的。他们的序列化和反序列化都是由这些数据库格式的客户端完成,并且文件的储存位置和数据布局(Data Layout)不由Hadoop控制,他们的文件切分也不是按HDFS的块大小(blocksize)进行切割。

2、为什么需要 RCFile

 

Facebook曾在2010 ICDE(IEEE International Conference on Data Engineering)会议上介绍了数据仓库Hive。Hive存储海量数据在Hadoop系统中,提供了一套类数据库的数据存储和处理机制。它采用类SQL语言对数据进行自动化管理和处理,经过语句解析和转换,最终生成基于Hadoop的MapReduce任务,通过执行这些任务完成数据处理。下图显示了Hive数据仓库的系统结构。 

 

 

Facebook在数据仓库上遇到的存储可扩展性的挑战是独一无二的。他们在基于Hive的数据仓库中存储了超过300PB的数据,并且以每日新增600TB的速度增长。去年这个数据仓库所存储的数据量增长了3倍。考虑到这个增长趋势,存储效率问题是facebook数据仓库基础设施方面目前乃至将来一段时间内最需要关注的。facebook工程师发表的RCFile: A Fast and Spaceefficient Data Placement Structure in MapReducebased Warehouse Systems一文,介绍了一种高效的数据存储结构——RCFile(Record Columnar File),并将其应用于Facebook的数据仓库Hive中。与传统数据库的数据存储结构相比,RCFile更有效地满足了基于MapReduce的数据仓库的四个关键需求,即Fast data loading、Fast query processing、Highly efficient storage space utilization和Strong adaptivity to highly dynamic workload patterns。RCFile 广泛应用于Facebook公司的数据分析系统Hive中。首先,RCFile具备相当于行存储的数据加载速度和负载适应能力;其次,RCFile的读优化可以在扫描表格时避免不必要的列读取,测试显示在多数情况下,它比其他结构拥有更好的性能;再次,RCFile使用列维度的压缩,因此能够有效提升存储空间利用率。

为了提高存储空间利用率,Facebook各产品线应用产生的数据从2010年起均采用RCFile结构存储,按行存储(SequenceFile/TextFile)结构保存的数据集也转存为RCFile格式。此外,Yahoo公司也在Pig数据分析系统中集成了RCFile,RCFile正在用于另一个基于Hadoop的数据管理系统Howl(http://wiki.apache.org/pig/Howl)。而且,根据Hive开发社区的交流,RCFile也成功整合加入其他基于MapReduce的数据分析平台。有理由相信,作为数据存储标准的RCFile,将继续在MapReduce环境下的大规模数据分析中扮演重要角色。

 

3、 RCFile 简介

 

facebook 的数据仓库中数据被加载到表里面时首先使用的存储格式是Facebook自己开发的Record-Columnar File Format(RCFile)。RCFile是一种“允许按行查询,提供了列存储的压缩效率”的混合列存储格式。它的核心思想是首先把Hive表水平切分成多个行组(row groups),然后组内按照列垂直切分,这样列与列的数据在磁盘上就是连续的存储块了。

当一个行组内的所有列写到磁盘时,RCFile就会以列为单位对数据使用类似zlib/lzo的算法进行压缩。当读取列数据的时候使用惰性解压策略( lazy decompression),也就是说用户的某个查询如果只是涉及到一个表中的部分列的时候,RCFile会跳过不需要的列的解压缩和反序列化的过程。通过在facebook的数据仓库中选取有代表性的例子实验,RCFile能够提供5倍的压缩比。

 

4、 超越RCFile,下一步采用什么方法

 

随着数据仓库中存储的数据量持续增长,FB组内的工程师开始研究提高压缩效率的技术和方法。研究的焦点集中在列级别的编码方法,例如行程长度编码(run-length encoding)、词典编码(dictionary encoding)、参考帧编码(frame of reference encoding)、能够在通用压缩过程之前更好的在列级别降低逻辑冗余的数值编码方法。 FB也尝试过新的列类型(例如JSON是在Facebook内部广泛使用的格式,把JSON格式的数据按照结构化的方式存储既可以满足高效查询的需求,同时也降低了JSON元数据存储的冗余)。

FB

的实验表明列级别的编码如果使用得当的话能够显著提高RCFile的压缩比。

 

与此同时,Hortonworks也在尝试类似的思路去改进Hive的存储格式。Hortonworks的工程团队设计和实现了ORCFile(包括存储格式和读写接口),这帮助Facebook的数据仓库设计和实现新的存储格式提供了一个很好的开始。

 

关于 ORCFile 的介绍请见这里: http://yanbohappy.sinaapp.com/?p=478

关于性能评测,笔者这里暂时没有条件,贴一张某次 hive 技术峰会演讲嘉宾的截图:

5、如何生成 RCFile 文件

上面说了这么多,想必你已经知道 RCFile 主要用于提升 hive 的查询效率,那如何生成这种格式的文件呢?

(1)hive 中直接 通过textfil e表进行insert转换

例如:

insert overwrite table http_RCTable partition(dt='2013-09-30') select p_id,tm,idate,phone from tmp_testp where dt='2013-09-30';

(2)通过 mapreduce 生成

 

目前为止,mapreduce 并没有提供内置 API 对 RCFile 进行支持,倒是 pig、hive、hcatalog 等 hadoop生态圈里的其他项目进行了支持,究其原因是因为 RCFile 相比 textfile 等其它文件格式,对于 mapreduce 的应用场景来说没有显著的优势。

 

为了避免重复造轮子,下面的生成 RCFile 的 mapreduce 代码调用了 hive 和  hcatalog 的相关类 ,注意你在测试下面的代码时,你的 hadoop、hive、 hcatalog 版本要一致,否则。。。你懂的。。。

比如我用的 hive-0.10.0+198-1.cdh4.4.0,那么就应该下载对应的版本: http://archive.cloudera.com/cdh4/cdh/4/

PS:下面的代码已经测试通过,木有问题。

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.serde2.columnar.BytesRefArrayWritable;
import org.apache.hadoop.hive.serde2.columnar.BytesRefWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.hcatalog.rcfile.RCFileMapReduceInputFormat;
import org.apache.hcatalog.rcfile.RCFileMapReduceOutputFormat;



public class TextToRCFile extends Configured implements Tool{

  
  
  public static class Map 
    	extends Mapper<Object, Text, NullWritable, BytesRefArrayWritable>{
    
    private byte[] fieldData;
    private int numCols;
    private BytesRefArrayWritable bytes;
    
    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
      numCols = context.getConfiguration().getInt("hive.io.rcfile.column.number.conf", 0);
      bytes = new BytesRefArrayWritable(numCols);
    }
    
    public void map(Object key, Text line, Context context
  ) throws IOException, InterruptedException {
      bytes.clear();
      String[] cols = line.toString().split("\\|");
      System.out.println("SIZE : "+cols.length);
      for (int i=0; i<numCols; i++){
          	fieldData = cols[i].getBytes("UTF-8");
          	BytesRefWritable cu = null;
              cu = new BytesRefWritable(fieldData, 0, fieldData.length);
              bytes.set(i, cu);
          }
      context.write(NullWritable.get(), bytes);
    }
  }
  
  @Override
  public int run(String[] args) throws Exception {
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    if(otherArgs.length < 2){
      	System.out.println("Usage: " +
      			"hadoop jar RCFileLoader.jar <main class> " +
      			"-tableName <tableName> -numCols <numberOfColumns> -input <input path> " +
      			"-output <output path> -rowGroupSize <rowGroupSize> -ioBufferSize <ioBufferSize>");
      	System.out.println("For test");
      	System.out.println("$HADOOP jar RCFileLoader.jar edu.osu.cse.rsam.rcfile.mapreduce.LoadTable " +
      			"-tableName test1 -numCols 10 -input RCFileLoaderTest/test1 " +
      			"-output RCFileLoaderTest/RCFile_test1");
      	System.out.println("$HADOOP jar RCFileLoader.jar edu.osu.cse.rsam.rcfile.mapreduce.LoadTable " +
      			"-tableName test2 -numCols 5 -input RCFileLoaderTest/test2 " +
      			"-output RCFileLoaderTest/RCFile_test2");
      	return 2;
      }
    
    /* For test
       
     */
    
      
    String tableName = "";
    int numCols = 0;
    String inputPath = "";
    String outputPath = "";
    int rowGroupSize = 16 *1024*1024;
    int ioBufferSize = 128*1024;
      for (int i=0; i<otherArgs.length - 1; i++){
      	if("-tableName".equals(otherArgs[i])){
      		tableName = otherArgs[i+1];
      	}else if ("-numCols".equals(otherArgs[i])){
      		numCols = Integer.parseInt(otherArgs[i+1]);
      	}else if ("-input".equals(otherArgs[i])){
      		inputPath = otherArgs[i+1];
      	}else if("-output".equals(otherArgs[i])){
      		outputPath = otherArgs[i+1];
      	}else if("-rowGroupSize".equals(otherArgs[i])){
      		rowGroupSize = Integer.parseInt(otherArgs[i+1]);
      	}else if("-ioBufferSize".equals(otherArgs[i])){
      		ioBufferSize = Integer.parseInt(otherArgs[i+1]);
      	}
      	
      }
      
      conf.setInt("hive.io.rcfile.record.buffer.size", rowGroupSize);
      conf.setInt("io.file.buffer.size", ioBufferSize);
      
      Job job = new Job(conf, "RCFile loader: loading table " + tableName + " with " + numCols + " columns");
      
      job.setJarByClass(TextToRCFile.class);
      job.setMapperClass(Map.class);
      job.setMapOutputKeyClass(NullWritable.class);
      job.setMapOutputValueClass(BytesRefArrayWritable.class);
//	    job.setNumReduceTasks(0);
      
      FileInputFormat.addInputPath(job, new Path(inputPath));
      
      job.setOutputFormatClass(RCFileMapReduceOutputFormat.class);
      RCFileMapReduceOutputFormat.setColumnNumber(job.getConfiguration(), numCols);
      RCFileMapReduceOutputFormat.setOutputPath(job, new Path(outputPath));
      RCFileMapReduceOutputFormat.setCompressOutput(job, false);
      
      
      System.out.println("Loading table " + tableName + " from " + inputPath + " to RCFile located at " + outputPath);
      System.out.println("number of columns:" + job.getConfiguration().get("hive.io.rcfile.column.number.conf"));
      System.out.println("RCFile row group size:" + job.getConfiguration().get("hive.io.rcfile.record.buffer.size"));
      System.out.println("io bufer size:" + job.getConfiguration().get("io.file.buffer.size"));
      
      return (job.waitForCompletion(true) ? 0 : 1);
  }
  
  public static void main(String[] args) throws Exception {
      int res = ToolRunner.run(new Configuration(), new TextToRCFile(), args);
      System.exit(res);
  }

}

6、Refer:

(1) 浅析Hadoop文件格式   http://www.infoq.com/cn/articles/hadoop-file-format

(2) Facebook数据仓库揭秘:RCFile高效存储结构   http://www.csdn.net/article/2011-04-29/296900

(3) Facebook的数据仓库是如何扩展到300PB的   http://yanbohappy.sinaapp.com/?p=478

(4) Hive架构   http://www.jdon.com/bigdata/hive.html

(5) Hive:ORC File Format存储格式详解   http://www.iteblog.com/archives/1014

(6) 普通文本压缩成RcFile的通用类   https://github.com/ysmart-xx/ysmart/blob/master/javatest/TextToRCFile.java

 

http://hugh-wangp.iteye.com/blog/1405804

基于HIVE文件格式的map reduce代码编写

http://smallboby.iteye.com/blog/1596776

普通文本压缩成RcFile的通用类

http://smallboby.iteye.com/blog/1592531

RcFile存储和读取操作

https://github.com/kevinweil/elephant-bird/blob/master/rcfile/src/main/java/com/twitter/elephantbird/mapreduce/output/RCFileOutputFormat.java

http://blog.csdn.net/liuzhoulong/article/details/79098

引自:http://www.tuicool.com/articles/YNfQn2

分享到:
评论

相关推荐

    Could not resolve dependencies for project org.apache.hive:hive-exec:jar:2.3.0:

    hive 开发UDF 使用maven工程 引发jar包缺失 hive 开发UDF 使用maven工程 引发jar包缺失

    C++解析windows注册表hive文件

    5. **解析键和值**:在数据块中,根据已知的Hive文件格式,解析键和值的结构。这涉及到读取和解码数据,如字符串、DWORD、QWORD等。 6. **递归解析子键**:由于键可以有子键,解析过程中需要递归地处理这些子结构。...

    HIVE安装及详解

    HIVE是一种基于Hadoop的数据仓库工具,主要用于处理和分析大规模数据。下面是关于HIVE的安装及详解。 HIVE基本概念 HIVE是什么?HIVE是一种数据仓库工具,主要用于处理和分析大规模数据。它将结构化数据文件转换为...

    hive-exec-*.jar包

    Missing Hive Execution Jar: /hive/hive1.2.1/lib/hive-exec-*.jar

    基于Hive的搜狗日志分析

    基于Hive的搜狗日志分析 本文档主要介绍了基于Hive的搜狗日志分析的整个过程,从数据预处理、构建数据仓库、数据分析到其他数据操作等方面进行了详细的介绍。 一、 数据预处理 数据预处理是整个日志分析的第一步...

    捕获hive脚本异常: echo $?

    在IT行业中,尤其是在大数据处理领域,Hive是一个广泛使用的数据仓库工具,它允许用户通过SQL-like语法查询存储在Hadoop集群中的大规模数据集。本文将深入探讨如何在执行Hive脚本时捕获并处理异常,以及如何利用...

    基于 Hive的数据分析案例 -MM聊天软件数据分析

    基于 Hive 的数据分析案例 -MM 聊天软件数据分析 本资源摘要信息主要介绍了基于 Hive 的数据分析案例,通过对 MM 聊天软件的数据进行统计分析,了解用户行为,实现精准的用户画像,并为公司的发展决策提供精确的...

    基于Hive的注册表

    在深入探讨之前,我们先了解基于Hive的注册表的基本概念及其重要性。 **基于Hive的注册表**是Windows CE 5.0引入的一种新的注册表管理机制,它将注册表数据存储在文件系统上的单个文件中,这些文件被称为**Hive**。...

    DBeaver链接hive驱动包下载: hive-jdbc-uber-2.6.5.0-292.jar

    在大数据处理领域,Hive作为一个基于Hadoop的数据仓库工具,广泛用于数据查询和分析。而DBeaver,作为一款跨平台的数据库管理工具,以其用户友好的界面和强大的功能,深受开发者喜爱。当需要在DBeaver中操作Hive...

    论文研究-基于Hive的海量搜索日志分析系统研究.pdf

    针对传统分布式模型在海量日志并行处理时的可扩展性和并行程序编写困难的问题, 提出了基于Hive的Web海量搜索日志分析机制。利用HQL语言以及Hadoop分布式文件系统(HDFS)和MapReduce编程模式对海量搜索日志进行分析...

    HIVE相关的jar包

    这个压缩包文件“HIVE相关的jar包”包含了不同版本的Hive库文件,这些文件对于在Java环境下开发和运行Hive应用程序至关重要。下面我们将详细讨论Hive jar包及其在IT领域的应用。 首先,Hive jar包是Hive服务的核心...

    Hive查询优化:Sort By、Order By、Cluster By、Distribute深入解析

    1. **基于Hadoop**:Hive建立在Hadoop文件系统(HDFS)之上,可以处理存储在HDFS中的大数据集。 2. **SQL-like Query Language**:Hive提供了一种称为HiveQL的查询语言,它是SQL的一种方言,允许用户执行数据查询、...

    基于Hadoop Hive健身馆可视化分析平台项目源码+数据库文件.zip

    基于Hadoop Hive健身馆可视化分析平台项目源码+数据库文件.zip启动方式 环境启动 hadoop hive2元数据库 sql导入 导入hivesql脚本,修改application.yml 启动主程序 HadoopApplication 基于Hadoop Hive健身馆可视化...

    基于SpringBoot+hiveJDBC+echarts的数据大屏可视化和大数据分析源码+项目使用说明.zip

    基于SpringBoot+hiveJDBC+echarts的数据大屏可视化和大数据分析源码+项目使用说明.zip 【项目介绍】 使用Hadoop技术可快速生成分析结果,对6万条美妆销售数据分析,将数据转化为有价值的数据。 在Centos7中搭建 ...

    基于hive旅游数据的分析与应用源码 基于hive旅游数据的分析与应用代码(高分毕设项目源码)

    1. 基于hive旅游数据的分析与应用源码代码说明:经导师指导并认可通过的98分毕设项目代码。 2.适用对象:本代码学习资料适用于计算机、电子信息工程、数学等专业正在做毕设的学生,需要项目实战练习的学习者,也适用...

    基于hive Hook的hive原数据调整

    ### 基于Hive Hook的Hive元数据调整 #### 问题背景及解决思路 在大数据处理领域,Apache Hive 是一个广泛使用的数据仓库工具,它提供了类 SQL 的查询语言 HiveQL,使得用户能够轻松地处理存储在 Hadoop 文件系统中...

    Hive内部表合并小文件Java程序

    在实际应用中,我们还可以考虑利用Hive自身的`COMPACTION`功能,它可以自动合并相同分区下的小文件。但是,自动合并可能不适用于所有情况,特别是在有特定性能需求或需要精确控制合并时机的场景下,自定义的Java程序...

    文件系统\注册表HIVE 解析库文件

    - HIVE文件是二进制格式,包含键、值对,用于存储和加载注册表信息。 - 解析库文件(如FS.DLL)可能包含用于读取、修改或解析注册表HIVE的函数。 3. FAT (File Allocation Table): - FAT是早期Windows和MS-DOS...

    HIVE文件读写

    1. 安装和配置Hadoop和Hive:在Linux服务器上安装Hadoop集群和Hive,确保所有依赖项正确配置,如Java环境、HDFS配置等。 2. 创建Hive表:使用HQL创建表结构,定义列名、数据类型以及可能的分区。例如: ```sql ...

Global site tag (gtag.js) - Google Analytics