Hive文件与记录格式
1. Hive文件与记录格式
Create table 有多种用法,例如STORED AS SEQUENCEFILE, ROW FORMAT DELIMITED, SERDE, INPUTFORMAT, OUTPUTFORMAT 这些语法。
某些语法是其他语法的快捷用法,例如:
语法 STORED AS SEQUENCEFILE 的替代方式是:指定INPUTFORMAT 为 org.apache.hadoop.mapred.SequenceFileInputFormat,并指定 OUTPUTFORMAT 为 org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat。
下面创建一些表,然后使用 DESCRIBE TABLE EXTENDED 语句查看下内部实际变化情况。首先创建一个简单表:
> create table text(x int);
hive> describe extended text;
OK
x int
Detailed Table Information
Table(tableName:text, dbName:default, owner:hadoop, createTime:1559016716, lastAccessTime:0, retention:0,
sd:StorageDescriptor(
cols:[FieldSchema(name:x, type:int, comment:null)],
location:hdfs://ip-10-0-2-70.cn-north-1.compute.internal:8020/user/hive/warehouse/text,
inputFormat:org.apache.hadoop.mapred.TextInputFormat,
outputFormat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat,
compressed:false,
numBuckets:-1,
serdeInfo:SerDeInfo(
name:null,
serializationLib:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,
parameters:{serialization.format=1}
),
bucketCols:[], sortCols:[], parameters:{},
skewedInfo:SkewedInfo(
skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}
),
storedAsSubDirectories:false),
partitionKeys:[], parameters:{totalSize=0, numRows=0, rawDataSize=0, COLUMN_STATS_ACCURATE={"BASIC_STATS":"true"}, numFiles=0, transient_lastDdlTime=1559016716},
viewOriginalText:null, viewExpandedText:null, tableType:MANAGED_TABLE, rewriteEnabled:false)
Time taken: 0.132 seconds, Fetched: 3 row(s)
然后再使用 STORED AS DEQUENCEFILE 语句创建一张表,用于对比:
> create table seq(x int) stored as sequencefile;
> describe extended seq;
OK
x int
Detailed Table Information
Table(tableName:seq, dbName:default, owner:hadoop, createTime:1559017290, lastAccessTime:0, retention:0,
sd:StorageDescriptor(
cols:[FieldSchema(name:x, type:int, comment:null)],
location:hdfs://ip-10-0-2-70.cn-north-1.compute.internal:8020/user/hive/warehouse/seq,
inputFormat:org.apache.hadoop.mapred.SequenceFileInputFormat,
outputFormat:org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat,
compressed:false, numBuckets:-1,
serdeInfo:SerDeInfo(
name:null, serializationLib:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,
parameters:{serialization.format=1}
),
bucketCols:[], sortCols:[], parameters:{},
skewedInfo:SkewedInfo(
skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}
),
storedAsSubDirectories:false
),
partitionKeys:[], parameters:{totalSize=0, numRows=0, rawDataSize=0, COLUMN_STATS_ACCURATE={"BASIC_STATS":"true"}, numFiles=0, transient_lastDdlTime=1559017290}, viewOriginalText:null, viewExpandedText:null, tableType:MANAGED_TABLE, rewriteEnabled:false)
两者差异很明显:STORED AS SEQUENCEFILE 与默认的InputFormat 和 OutputFormat的值不一样:
inputFormat:org.apache.hadoop.mapred.TextInputFormat,
outputFormat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat,
inputFormat:org.apache.hadoop.mapred.SequenceFileInputFormat,
outputFormat:org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat,
在从表中读取数据时,Hive 会使用InputFormat,在向表写入数据时,会使用OutputFormat。InputFormat会从文件中读取key-value对。默认情况下,Hive会直接忽略掉key的内容,而是只有value中的数据。因为key来自于TextInputFormat,是每行的字节偏移量,并不是用户的数据。
2.文件格式
Hive中最简单的数据格式是文本文件格式,可以使用任意分隔符进行分割,同时它也是默认的文件格式,等价于:在创建时通过STORED AS TEXTFILE 语句指定使用文本存储格式
文本文件便于与其他工具共享数据,也便于查看和编辑。不过,相对于二进制文件,文本文件存储的空间要大。我们可以使用压缩,但是如果使用二进制文件存储格式的话,则既可以节约存储空间,也可以提高I/O性能。
2.1 SequenceFile
其中一种存储格式是SequenceFile文件存储格式,在定义表结构时可以通过STORED AS SEQUENCEFILE 语句指定。SequenceFile 是Hadoop生态系统中支持的标准文件格式,可以在块级别和记录级别进行压缩,这对于优化磁盘利用率和I/O来说非常有意义。同时仍然可以支持按照块级别的文件分割,以方便并行处理。Hive 所支持的另一个高效二进制文件是RCFile
2.2 RCFile
大多数Hadoop和Hive都是行式存储的,大多数场景下,这是比较高效的。高效的原因有:
1. 大多数的表具有的字段个数都不大(一般1到20个字段)
2. 对文件按块进行压缩对于需要处理重复数据的情况比较高
3. 很多的处理和调试工具(例如more、head、awk)都可以很好地应用于行式存储数据
但是对于某些特定类型的数据和应用,列式存储会更适用。例如,表中有成百上千个字段,但是大多数查询仅使用其中小部分字段,这时扫描所有的行和过滤掉大部分数据显然是很浪费的。如果数据存储是列式存储,那么仅扫描需要的列数据就可以提高性能。
对于列式存储,进行压缩通常会非常高效,特别是在这列的数据具有较低计数的时候。同时,一些列式存储并不需要物理存储null值的列。
基于这些场景,Hive中设计了RCFile。
Hive 另外一个优点是:可以很容易地在不同的存储格式间转换数据。对一个表执行一个SELECT查询时,或是向表写入执行INSERT操作时,Hive会使用这个表的metadata信息,自动执行转换过程,而不需要额外的程序来对不同存储格式进行转换。
这里我们举一个例子,首先使用ColumarSerDe、RCFileInputFormat和RCFileOutputFormat参数创建表:
> select * from a;
OK
4 5
3 2
> create table columnTable(key int, value int)
> ROW FORMAT SERDE
> 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe'
> STORED AS
> INPUTFORMAT 'org.apache.hadoop.hive.ql.io.RCFileInputFormat'
> OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.RCFileOutputFormat';
OK
hive> FROM a INSERT OVERWRITE TABLE columnTable SELECT a.key, a.value;
对于 RCFile 来说,无法使用通常工具打开RCFile,也无法使用通常打开SequenceFile的工具打开。例如:
>cat 000000_0
RCF hive.io.rcfile.column.number2Ч];E3:'c
4352
不过Hive 提供了一个rcfilecat工具,用于展示RCFile文件内容:
> hive --service rcfilecat /user/hive/warehouse/columntable/000000_0
4 5
3 2
3. 记录格式:SerDe
SerDe是Serializer/Deserializer的简称。一个SerDe允许Hive从一个表读入数据,并以任意用户定义的格式写回HDFS。它包含了将一条记录的非结构化数据转化成Hive可以使用的一条记录的过程。
Hive SerDe 库在 org.apache.hadoop.hive.serde2 中(旧版本的SerDe 库在 org.apache.hadoop.hive.serde中,已经被弃用),它本身包含了一些内置的SerDes,如:
1. Avro(Hive 0.9.1 及之后版本)
2. ORC(Hive 0.11 及之后版本)
3. RegEx
4. Thrift
5. Parquet(Hive 0.13及之后版本)
6. CSV(Hive 0.14及之后版本)
7. JsonSerDe(Hive 0.12 及之后版本,在hcatalog-core中)
需要注意的是:在Hive 0.12 之前的发行版中,Amazon提供了一个JSON SerDe,位于s3://elasticmapreduce/samples/hive-ads/libs/jsonserde.jar
也有用户定义的SerDes,不过需要用户实现,或是使用第三方的SerDe。
SerDe的用途与过程有以下三点:
· Hive 使用SerDe(以及FileFormat)读写表中的行
· HDFS文件 --> InputFormat --> <key, value> --> Deserializer --> Row object
· Row object --> Serializer --> <key, value> --> OutputFormat --> HDFS files
这里需要注意的是:这里的key部分在读入后是被忽略掉的(因为key来自于TextInputFormat,是每行的字节偏移量,并不是用户的数据),基本上行对象是存在value中的。
在内部,Hive 引擎使用定义的InputFormat来读取一行条目,然后此记录会被传递给SerDe.Deserializer() 方法进行处理。
以JSON SerDe为例,如果用户想使用Hive 查询JSON格式的数据。若是不使用SerDe,且每行为一个json“文件”的话,则可以在使用TextInputFormat 读入,然后使用一个JSON的SerDe 将JSON文档作为一条记录进行解析。例如:
> create external table messages(
> id int,
> message string
> )
> row format serde "org.apache.hive.hcatalog.data.JsonSerDe"
> location 's3://tang-emr/jsonserde/'
> ;
JSON数据为:
{"id":1,"message":"yep"}
{"id":2,"message":"asdf"}
{"id":3,"message":"cddacddc","fa":"asf"}
hive> select * from messages;
OK
1 yep
2 asdf
3 cddacddc
References:
1. Hive 编程指南