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

2024-03-18 16:20

本文主要是介绍基于Hive 的文件格式:RCFile 简介及其应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录[-]

  • 1、hadoop 文件格式简介
  • (1)SequenceFile
  • (2)RCFile
  • (3)Avro
  • (4)文本格式
  • (5)外部格式
  • 2、为什么需要 RCFile
  • 3、RCFile 简介
  • 4、超越RCFile,下一步采用什么方法
  • 5、如何生成 RCFile 文件
  • (1)hive 中直接通过textfile表进行insert转换
  • (2)通过 mapreduce 生成
  • 6、Refer:

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

1、hadoop 文件格式简介

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

(1SequenceFile

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)Avro

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 中直接通过textfile表进行insert转换

例如:

?
1
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:下面的代码已经测试通过,木有问题。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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/7909863


转载自:http://my.oschina.net/leejun2005/blog/280896?utm_source=tuicool

(若有问题,请与本人联系,谢谢)

这篇关于基于Hive 的文件格式:RCFile 简介及其应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/822909

相关文章

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Python调用另一个py文件并传递参数常见的方法及其应用场景

《Python调用另一个py文件并传递参数常见的方法及其应用场景》:本文主要介绍在Python中调用另一个py文件并传递参数的几种常见方法,包括使用import语句、exec函数、subproce... 目录前言1. 使用import语句1.1 基本用法1.2 导入特定函数1.3 处理文件路径2. 使用ex

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象