Hive之FileFormats & SerDe
1 FileFormat概念
首先什么是Hive的FileFormat?
Hive本身没有存储数据的能力,底层存储数据还得依靠Haddop的HDFS,HDFS上的数据可能是固定格式或者特殊格式的数据,通过FileFormat可以将数据格式与Hive的每一行Row对应起来,形成Hive的Table,这些Table的元数据都存储在Hive的MetaData数据库中,通过QueryProcessor组件中的MetaDataLayer访问元数据,这样的话就可以通过SQL的形式访问Hive的表中的数据了。
怎么通过Hive关联HDFS的数据?
CREATE TABLE TABLENAME ...
LOCATION 'HDFS://XXXX';
LOAD DATA INPATH INTO TABLE TABLENAME [PARTITION()];
一般什么时候用FileFormat?
FileFormat一般用于创建表的时候创建,或者修改表【分区】的时候使用使用,具体案例如下:
/* 使用方法一 */
/* Hive原生默认的FileFormat指定格式,还可以指定正则匹配的模式*/
CREATE TABLE IF NOT EXISTS tablename()
COMMENT ''
PARTITIONED BY (dt string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
MAP KEYS TERMINATED BY ':'
COLLECTION ITEMS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS ORC;
/* 使用方法二 */
/*一般用于不同特殊格式的文件如ORC、Parquet、Avro等*/
CREATE TABLE IF NOT EXISTS tablename()
COMMENT ''
PARTITIONED BY (dt string)
ROW FORMAT SERDE 'SERDE CLASS NAME'
STORED AS
INPUTFORMAT ''
OUTPUTFORMAT '';
/*修改表的FILEFORMAT*/
ALTER TABLE TABLENAME [PARTITION()] SET FILEFORMAT ORC;
2 Hive SerDe
什么是SerDe?
SerDe是Serializer & DeSerializer的简称,Hive中的数据的流程走向可以分为
读、写
。
读
:HDFS File=>InputFormat(RecordReader) =><key,value>=>Deserializer=>Row object
写
:Row object=> Serializer=> <key,value>=> OurputFormat => HDFS File
Hive原则上是不拥有HDFS的数据的,那么怎么将HDFS的数据关联到Hive的表呢。
-- 1、外部表关联的形式,数据不受Hive管理,Drop table的时候只会删除对应的MetaData,数据依旧保存在HDFS上。
CREATE EXTERNAL TABLE() LOCATION 'HDFS://PATH';
-- 2 通过load将文件移到Hive的指定目录。
CREATE TABLE TABLENAME.....;
LOAD DATA INPAHT INTO TABLE TABLENAME [PARTITION()] ;
Hive目前有2个serde库,支持用户自定义SerDe的实体并投入到使用。
# 将会被deprecated
old=org.apache.hadoop.hive.serde
# 最新的serde库
new=org.apache.hadoop.hive.serde2
3 Hive原生内置的SerDe
3.1 Avro (Hive-0.9.1 and later)
3.1.1 Hive与Avro的版本适配
Hive version | avro version |
---|---|
Hive 0.9.1 | Avro 1.5.3 |
Hive 0.10\0.11\0.12 | Avro 1.7.1 |
Hive 0.13 and 0.14 | Avro 1.7.5 |
-- table的数据最终保存成Avro
CREATE TABLE kst
PARTITIONED BY (ds string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
TBLPROPERTIES (
'avro.schema.url'='http://schema_provider/kst.avsc');
-- 已有Avro数据
CREATE EXTERNAL TABLE kst1()
LOCATION 'hdfs://avro\'s parent dictory';
3.1.2 Avro到Hive的类型转换
Avro类型 | Hive类型 | Note描述 |
---|---|---|
boolean | boolean | |
bytes | binary | Bytes are converted to Array[smallint] prior to Hive 0.12.0. |
double | double | |
enum | string | Hive has no concept of enums. |
fixed | binary | Fixeds are converted to Array[smallint] prior to Hive 0.12.0. |
float | float | |
int | int | |
list | array | |
long | bigint | |
map | map | |
null | void | |
record | struct | |
string | string | |
union | union | Unions of [T, null] transparently convert to nullable T, other types translate directly to Hive’s unions of those types. However, unions were introduced in Hive 7 and are not currently able to be used in where/group-by statements. They are essentially look-at-only. Because the AvroSerde transparently converts [T,null], to nullable T, this limitation only applies to unions of multiple types or unions not of a single type and null. |
NOTE:如果出现了问题排查的话可以在操作的时候通过
bin/hive --hiveconf hive.root.logger=INFO,console*
如果在desc avroname 或者 select * from avrotablename时出现error-error…时,那么我们可以设置:
alter table avrotablename set TBLPROPERTIES(
avro.schema.literal =
avro.avro.schema.url =
);
3.2 ORC (Hive-0.11 and later)
3.2.1 ORC概念
什么是ORC?
ORC是一种典型的列式存储格式,全称是(Optimized Row Columnar),提供高效的方式去存储数据,它被设计出来的初衷是解决其他Hive的文件格式的限制,使用ORC可以在读、写、处理数据的时候提高明显的性能提升。
3.2.2 ORC的特点
1、在处理的时候一个Task只会产生一个文件,减轻NameNode的负载。
2、与Hive的DateTime、Decimal以及其他的数据类型(struct、map、list、union)完美支持。
3、ORC文件中存储了轻量级的index data,这样允许跳过对应的row group(stripes),更快的寻找到所指定的row。
4、基于数据类型的block-mode的压缩,而不是record-mode级别,数据类型& String类型压缩方式不同。
5、可以使用不同的RecordReaders对同一个文件进行并发读取。
6、可以提供在不需要扫描和标记的情况下对文件进行切分的能力。
7、ORC文件绑定了reading、writing所需要的内存量。
8、元数据基于Protocol Buffer存储,可以支持对不同字段的删除、增加。
3.2.3 ORC的文件结构
3.2.4 ORC的文件结构解读
如上图所示,每个ORC文件都包含多个Stripes(Row Groups)
、FileFooter、PostScript
。
-
FileFooter是文件的辅助信息,包含ORC文件中的所有Stripe的信息集合、每个Stripes对应的行数、每列的数据类型,同时还包含一些列级别的聚合操作如sum、count、min、max等;
-
PostScript保存着的是压缩的参数、还有压缩后的大小标注;
-
Stripe是由多个Row Groups组成的,默认是250M,strpe越大读取HDFS的时候效率越高。
-
每个Stripe又是由
IndexData、RowData、StripeFooter
组成 -
RowData
是存储的实际数据,用来进行table scan -
Stripe footer
包含一个数据流的目录地址 -
IndexData
包含每个column的max、min值,以及每个column值的row位置(包含1个bit的field或者布隆过滤器),每个Index节点提供了offsets允许寻找到对应压缩block以及解压后的字节数据,index只是用来选择出对应的stripes而不是作为查询的应答结果。- 有了相当频率的index节点,这就允许在stripe中通过row-skipping的形式进行快速read,尤其是大的stripe size,默认的是每次能跳过10000行。
-
3.2.5 如何指定ORC FileFormat
一个简单的案例如下。
1 SET hive.default.fileformat = orc;
2 CREATE TABLE TESTORC() STORED AS ORC;
3 ALTER TABLE TESTORC [PARTITION()] SET FIELFORMAT ORC;
--------------------
create table Addresses (
name string,
street string,
city string,
state string,
zip int
) stored as orc tblproperties ("orc.compress"="snappy");
3.2.6 ORC相关的TBLPROPERTIES
属性值key | 默认值 | 描述 |
---|---|---|
orc.compress | ZLIB | high level compression (one of NONE, ZLIB, SNAPPY) |
orc.compress.size | 262,144 | number of bytes in each compression chunk |
orc.stripe.size | 67,108,864 | number of bytes in each stripe |
orc.row.index.stride | 10,000 | number of rows between index entries (must be >= 1000) |
orc.create.index | true | whether to create row indexes |
orc.bloom.filter.columns | “” | comma separated list of column names for which bloom filter should be created |
orc.bloom.filter.fpp | 0.05 | false positive probability for bloom filter (must >0.0 and <1.0) |
3.3 Regex (正则weblog格式)
CREATE TABLE apachelog (
host STRING,
identity STRING,
user STRING,
time STRING,
request STRING,
status STRING,
size STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^]*) ([^]*) ([^]*) (-|\\[^\\]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\".*\") ([^ \"]*|\".*\"))?"
)
STORED AS TEXTFILE;
3.4 Parquet (Hive-0.13 and later)
3.4.1 Parquet介绍
Parquet对Hadoop来说是一个支持宽表的列式存储格式,支持多种引擎读写parquet格式,常用的有 Hive、impala、spark,具体参考engine。
3.4.2 Parquet使用语法
parquet的使用语法基于不同的Hive版本
3.4.2.1 Hive 0.10-0.12
由于Hive0.10-0.12对Parquet还没有提供原生的支持,我们必须将parquet-hive-bundle jar引入到Hive lib,然后通过以下SQL语句。
CREATE TABLE parquet_test (
id int,
str string,
mp MAP<STRING,STRING>,
lst ARRAY<STRING>,
strct STRUCT<A:STRING,B:STRING>)
PARTITIONED BY (part string)
ROW FORMAT SERDE 'parquet.hive.serde.ParquetHiveSerDe'
STORED AS
INPUTFORMAT 'parquet.hive.DeprecatedParquetInputFormat'
OUTPUTFORMAT 'parquet.hive.DeprecatedParquetOutputFormat';
3.4.2.2 Hive 0.13
0.13版本的Hive对Parquet提供了原生的支持。
CREATE TABLE parquet_test (
id int,
str string,
mp MAP<STRING,STRING>,
lst ARRAY<STRING>,
strct STRUCT<A:STRING,B:STRING>)
PARTITIONED BY (part string)
STORED AS PARQUET;
3.5 CSV (Hive-0.14 and later)
CREATE TABLE my_table(a string, b string, ...)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
"separatorChar" = "\t",
"quoteChar" = "'",
"escapeChar" = "\\"
)
STORED AS TEXTFILE;
3.6 JsonSerDe(Hive-0.12 and later)
/* Hive 0.12 - 3.0.0*/
ADD JAR /usr/lib/hive-hcatalog/lib/hive-hcatalog-core.jar;
CREATE TABLE my_table(a string, b bigint, ...)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE;
/* Hive 3.0.0 and later */
CREATE TABLE my_table(a string, b bigint, ...)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe'
STORED AS TEXTFILE;
--或者
CREATE TABLE my_table(a string, b bigint, ...) STORED AS JSONFILE;