本文为自己翻译的译文,原文地址:https://cwiki.apache.org/confluence/display/Hive/AvroSerDe
最早支持AvroSerDe的版本
The AvroSerde is available in Hive 0.9.1 and greater.
AvroSerde允许用户读取或写入Avro数据到Hive表。以下是AvroSerde的注意事项:
有关SerDes的一般信息,请参阅开发指南中的Hive SerDe。还请参阅SerDe,了解输入和输出处理的详细信息。
The AvroSerde has been built and tested against Hive 0.9.1 and later, and uses Avro 1.7.5 as of Hive 0.13 and 0.14.
Hive Versions
|
Avro Version
|
---|---|
Hive 0.9.1 | Avro 1.5.3 |
Hive 0.10, 0.11, and 0.12 | Avro 1.7.1 |
Hive 0.13 and 0.14 | Avro 1.7.5 |
While most Avro types convert directly to equivalent Hive types, there are some which do not exist in Hive and are converted to reasonable equivalents. Also, the AvroSerde special cases unions of null and another type, as described below:
Avro type |
Becomes Hive type |
Note |
---|---|---|
null |
void |
|
boolean |
boolean |
|
int |
int |
|
long |
bigint |
|
float |
float |
|
double |
double |
|
bytes |
binary |
在Hive 0.12.0之前,bytes被转换为数组[smallint]。 |
string |
string |
|
record |
struct |
|
map |
map |
|
list |
array |
|
union |
union |
[T, null]的联合显式地转换可为空的T,其他类型直接转换为Hive的类型结合。然而,在Hive 7中引入了union,目前还不能在where/group-by语句中使用。从本质上说,他们只是能够看到。因为AvroSerde显式地将[T,null]转换为nullable T,这个限制只适用于多个类型联合或组合的联合,而不是单个类型和null。 |
enum |
string |
Hive没有enums的概念。 |
fixed |
binary |
Fixeds在Hive 0.12.0之前被转换成数组[smallint]。 |
使用AvroSerDe可以在Hive中创建avro支持的表。
创建Avro-backed表,使用org.apache.hadoop.hive.serde2.avro.AvroSerDe指定serde ,指定输入格式为org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat和输出格式为org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat。还提供了一个位置,AvroSerde将从该位置提取大部分表的当前模式。例如:
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'
);
|
在这个示例中,我们从一个webserver中提取了“真相”阅读器模式。下面描述了提供这个模式的其他参数。
Avro文件添加到数据库(或者创建一个外部表)使用标准的Hive操作(http://wiki.apache.org/hadoop/Hive/LanguageManual/DML)。
此表的描述如下:
hive> describe kst;
OK
string1 string from deserializer
string2 string from deserializer
int1
int
from deserializer
boolean1
boolean
from deserializer
long1 bigint from deserializer
float1
float
from deserializer
double1
double
from deserializer
inner_record1 struct enum1 string from deserializer
array1 array
map1 map
union1 uniontype<
float
,
boolean
,string> from deserializer
fixed1 binary from deserializer
null1
void
from deserializer
unionnullint
int
from deserializer
bytes1 binary from deserializer
|
在这一点上,avo支持的表可以像任何其他表一样在Hive中工作。
从Hive 0.14开始,可以通过在DDL语句中使用“STORED AS AVRO”来创建AVRO支持的表。AvroSerDe负责从Hive表模式中创建合适的Avro模式,这在Hive的Avro可用性方面取得了很大的成功。
例如:
CREATE TABLE kst (
string1 string,
string2 string,
int1
int
,
boolean1
boolean
,
long1 bigint,
float1
float
,
double1
double
,
inner_record1 struct
enum1 string,
array1 array
map1 map
union1 uniontype<
float
,
boolean
,string>,
fixed1 binary,
null1
void
,
unionnullint
int
,
bytes1 binary)
PARTITIONED BY (ds string)
STORED AS AVRO;
|
这个表的描述如下:
hive> describe kst;
OK
string1 string from deserializer
string2 string from deserializer
int1
int
from deserializer
boolean1
boolean
from deserializer
long1 bigint from deserializer
float1
float
from deserializer
double1
double
from deserializer
inner_record1 struct enum1 string from deserializer
array1 array
map1 map
union1 uniontype<
float
,
boolean
,string> from deserializer
fixed1 binary from deserializer
null1
void
from deserializer
unionnullint
int
from deserializer
bytes1 binary from deserializer
|
AvroSerde可以将任何Hive表序列化为Avro文件。这使得它可以高效的转换任意Hive类型为Avro格式文件。为了将一个表写入Avro文件,您首先必须创建一个适当的Avro Schema(除了Hive 0.14.0及后续版本,如下面所述)。创建使用select语法语句当前不受支持。
类型转换如表中所示。对于不直接翻译的类型,有几项需要记住:
Hive对于类型非常宽容:它将尝试在新表的等价列中存储与所提供的列匹配的任何值。例如,没有对列名进行匹配。因此,在查询编写器中,必须确保目标列类型是正确的。如果不是,Avro可以接受该类型,否则可能会抛出异常:这取决于特定类型的组合。
查看下面的Hive表,它涵盖了所有类型的Hive数据类型,使它成为一个很好的例子::
CREATE TABLE test_serializer(string1 STRING,
int1 INT,
tinyint1 TINYINT,
smallint1 SMALLINT,
bigint1 BIGINT,
boolean1 BOOLEAN,
float1 FLOAT,
double1 DOUBLE,
list1 ARRAY
map1 MAP
struct1 STRUCT
union1 uniontype
enum1 STRING,
nullableint INT,
bytes1 BINARY,
fixed1 BINARY)
ROW FORMAT DELIMITED FIELDS TERMINATED BY
','
COLLECTION ITEMS TERMINATED BY
':'
MAP KEYS TERMINATED BY
'#'
LINES TERMINATED BY
'\n'
STORED AS TEXTFILE;
|
如果表是由csv文件支持的,例如:
why hello there |
42 |
3 |
100 |
1412341 |
true |
42.43 |
85.23423424 |
alpha:beta:gamma |
Earth#42:Control#86:Bob#31 |
17:true:Abe Linkedin |
0:3.141459 |
BLUE |
72 |
^A^B^C |
^A^B^C |
another record |
98 |
4 |
101 |
9999999 |
false |
99.89 |
0.00000009 |
beta |
Earth#101 |
1134:false:wazzup |
1:true |
RED |
NULL |
^D^E^F^G |
^D^E^F |
third record |
45 |
5 |
102 |
999999999 |
true |
89.99 |
0.00000000000009 |
alpha:gamma |
Earth#237:Bob#723 |
102:false:BNL |
2:Time to go home |
GREEN |
NULL |
^H |
^G^H^I |
然后你可以把它写成下面描述的Avro。
为了将这个表保存为Avro文件,创建一个等效的Avro模式(记录的名称空间和实际名称不重要):
{
"namespace"
:
"com.linkedin.haivvreo"
,
"name"
:
"test_serializer"
,
"type"
:
"record"
,
"fields"
: [
{
"name"
:
"string1"
,
"type"
:
"string"
},
{
"name"
:
"int1"
,
"type"
:
"int"
},
{
"name"
:
"tinyint1"
,
"type"
:
"int"
},
{
"name"
:
"smallint1"
,
"type"
:
"int"
},
{
"name"
:
"bigint1"
,
"type"
:
"long"
},
{
"name"
:
"boolean1"
,
"type"
:
"boolean"
},
{
"name"
:
"float1"
,
"type"
:
"float"
},
{
"name"
:
"double1"
,
"type"
:
"double"
},
{
"name"
:
"list1"
,
"type"
:{
"type"
:
"array"
,
"items"
:
"string"
} },
{
"name"
:
"map1"
,
"type"
:{
"type"
:
"map"
,
"values"
:
"int"
} },
{
"name"
:
"struct1"
,
"type"
:{
"type"
:
"record"
,
"name"
:
"struct1_name"
,
"fields"
: [
{
"name"
:
"sInt"
,
"type"
:
"int"
}, {
"name"
:
"sBoolean"
,
"type"
:
"boolean"
}, {
"name"
:
"sString"
,
"type"
:
"string"
} ] } },
{
"name"
:
"union1"
,
"type"
:[
"float"
,
"boolean"
,
"string"
] },
{
"name"
:
"enum1"
,
"type"
:{
"type"
:
"enum"
,
"name"
:
"enum1_values"
,
"symbols"
:[
"BLUE"
,
"RED"
,
"GREEN"
]} },
{
"name"
:
"nullableint"
,
"type"
:[
"int"
,
"null"
] },
{
"name"
:
"bytes1"
,
"type"
:
"bytes"
},
{
"name"
:
"fixed1"
,
"type"
:{
"type"
:
"fixed"
,
"name"
:
"threebytes"
,
"size"
:
3
} }
] }
|
然后你可以把它写到Avro文件:
CREATE TABLE as_avro
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'
=
'file:///path/to/the/schema/test_serializer.avsc'
);
INSERT OVERWRITE TABLE as_avro SELECT * FROM test_serializer;
|
在Hive版本0.14和之后,您不需要手动创建Avro模式。上面所示的程序将一个表保存为Avro文件,减少到一个DDL语句,然后插入到表中。
CREATE TABLE as_avro(string1 STRING,
int1 INT,
tinyint1 TINYINT,
smallint1 SMALLINT,
bigint1 BIGINT,
boolean1 BOOLEAN,
float1 FLOAT,
double1 DOUBLE,
list1 ARRAY
map1 MAP
struct1 STRUCT
union1 uniontype
enum1 STRING,
nullableint INT,
bytes1 BINARY,
fixed1 BINARY)
STORED AS AVRO;
INSERT OVERWRITE TABLE as_avro SELECT * FROM test_serializer;
|
虽然由Hive作业编写的文件是有效的Avro文件,然而,MapReduce并没有添加标准的. avro扩展。如果您将这些文件复制出来,您可能要用.avro重命名它们。
有三种方法可以为Avro表提供读者模式,所有这些方法都涉及到serde的参数。随着模式的发展,您可以通过更新表中的参数来更新这些值。
指定访问模式的URL。对于http模式,这适用于测试和小规模集群,但由于在作业中每个任务中至少会访问一个模式,因此可以快速将工作转换为针对URL的DDOS攻击程序(例如,web服务器)。除了测试之外,使用此参数时要谨慎。
模式也可以指向HDFS上的一个位置,例如:hdfs://your-nn:9000/path/to/avsc/file。然后AvroSerde将读取来自HDFS的文件,该文件应该对许多读取同时提供弹性。请注意,serde将从每个mapper读取这个文件,因此一个好的方法是将模式文件的复制转换为高值为读取提供良好的位置。模式文件本身应该是相对较小的,因此这不会在过程中增加大量的开销。
您可以将模式直接嵌入到create语句中。如果模式没有任何单引号(或者它们被适当地转义了),那么这就起作用了,因为Hive使用它来定义参数值。例如:
CREATE TABLE embedded
COMMENT
"just drop the schema right into the HQL"
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.literal'
='{
"namespace"
:
"com.howdy"
,
"name"
:
"some_schema"
,
"type"
:
"record"
,
"fields"
: [ {
"name"
:
"string1"
,
"type"
:
"string"
}]
}');
|
注意,该值被括在单引号中并粘贴到create语句中。
Hive可以做简单的变量替换,您可以将嵌入在变量中的模式传递给脚本。注意,要做到这一点,模式必须完全转义(回车转换为\n,标签到\t,引号转义等)。一个例子:
set hiveconf:schema;
DROP TABLE example;
CREATE TABLE example
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.literal'
=
'${hiveconf:schema}'
);
|
要执行这个脚本文件,假设$SCHEMA被定义为转义模式值:
hive --hiveconf schema=
"${SCHEMA}"
-f your_script_file.sql
|
注意,$SCHEMA被插入到引号中,以正确处理模式中的空格。
Hive没有提供一个简单的方法来取消或删除一个属性。如果您希望从一种使用URL或模式切换到另一种,则将被忽略的值设置为none, AvroSerde将把它视为未设置。
Hive 0.14.0支持在HBase列中存储和查询Avro对象,使其可视为Hive结构。这使得Hive能够对HBase数据进行特别的分析,这些数据可以被深度结构化。在0.14.0之前,HBase Hive集成只支持在列中查询原始数据类型。有关详细信息,请参阅存储在HBase列中的Avro数据。
在工作提交之前,Hive倾向于从AvroSerde中接收异常。为了使Hive更加冗长,它可以用*hive --hiveconf hive.root.logger=INFO,console*启动,它将向控制台发送大量的信息,并且可能包含AvroSerde正在试图告诉你哪里出了问题的所有信息。如果AvroSerde在MapReduce期间遇到错误,将在失败的任务日志中提供堆栈跟踪,这可以从JobTracker的web界面进行检查 。AvroSerde只发出AvroSerdeException;请在所有的错误报告中包含这些内容。最常见的是在试图序列化与Avro所期望的不兼容类型时出现的异常。
AvroSerde在查找或解析avro.schema提供的模式时返回此消息。文字或avro.avro.schema。url的值。它不能更具体,因为Hive期望所有调用serde配置方法都是成功的,这意味着我们不能返回一个实际的异常。通过这个消息发送一个错误,表被保存在一个良好的状态中,错误的值可以通过调用alter table T set TBLPROPERTIES来纠正。