AvroSerDe

Availability

Earliest version AvroSerde is available

AvroSerde 在 Hive 0.9.1 和更高版本中可用。

概述–从 Hive 使用 Avro

AvroSerde 允许用户读取或写入Avro data作为 Hive 表。 AvroSerde 的要点:

  • 从 Avro 架构推断 Hive 表的架构。从Hive 0.14开始,可以从 Hive 表模式中推断 Avro 模式。

  • 利用 Avro 的向后兼容性功能,根据指定的架构读取表中的所有 Avro 文件

  • 支持任意嵌套的架构。

  • 将所有 Avro 数据类型转换为等效的 Hive 类型。大多数类型可以精确 Map,但是某些 Avro 类型在 Hive 中不存在,并由 AvroSerde 自动转换。

  • 了解压缩的 Avro 文件。

  • 透明地将处理可为 null 的类型的 Avro 习惯转换为 Union [T,null]转换为 T,并在适当时返回 null。

  • 将任何 Hive 表写入 Avro 文件。

  • 在我们的 ETL 流程中,已经可靠地针对最复杂的 Avro 模式进行了工作。

  • Hive 0.14开始,可以使用Alter Table语句将列添加到 Avro 支持的 Hive 表中。

有关 SerDes 的一般信息,请参阅《开发人员指南》中的Hive SerDe。另请参阅SerDe,以获取有关 Importing 和输出处理的详细信息。

Requirements

AvroSerde 已针对 Hive 0.9.1 及更高版本进行了构建和测试,并从 Hive 0.13 和 0.14 开始使用 Avro 1.7.5.

Hive VersionsAvro Version
Hive 0.9.1Avro 1.5.3
配置单元 0.10、0.11 和 0.12Avro 1.7.1
配置单元 0.13 和 0.14Avro 1.7.5

Avro 到 Hive 的类型转换

虽然大多数 Avro 类型直接转换为等效的 Hive 类型,但是有些在 Hive 中不存在,而是转换为合理的等效形式。同样,AvroSerde 特殊情况下的 null 和另一个类型的并集,如下所述:

Avro type成为 Hive 类型Note
nullvoid
booleanboolean
intint
longbigint
floatfloat
doubledouble
bytesbinary在 Hive 0.12.0 之前,将字节转换为 Array [smallint]。
stringstring
recordstruct
mapmap
listarray
unionunion[T,null]的并集透明地转换为可为空的 T,其他类型直接转换为这些类型的 Hive 的并集。但是,联合是在 Hive 7 中引入的,当前不能在 where/group-by 语句中使用。它们本质上是仅查看对象。因为 AvroSerde 透明地将[T,null]转换为可空 T,所以此限制仅适用于多种类型的并集或非单一类型且为 null 的并集。
enumstringHive 没有枚举的概念。
fixedbinary在 Hive 0.12.0 之前,固定值将转换为 Array [smallint]。

创建 Avro 支持的 Hive 表

可以使用 AvroSerDe 在 Hive 中创建支持 Avro 的表。

所有 Hive 版本

要创建支持 Avro 的表,请将 Serde 指定为 org.apache.hadoop.hive.serde2.avro.AvroSerDe,将 Importing 格式指定为 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');

在此示例中,我们从 Web 服务器中提取了真实的阅读器架构。下面介绍了提供模式的其他选项。

使用标准的 Hive 操作(http://wiki.apache.org/hadoop/Hive/LanguageManual/DML)将 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<int_in_inner_record1:int,string_in_inner_record1:string> from deserializer
enum1   string  from deserializer
array1  array<string>   from deserializer
map1    map<string,string>      from deserializer
union1  uniontype<float,boolean,string> from deserializer
fixed1  binary  from deserializer
null1   void    from deserializer
unionnullint    int     from deserializer
bytes1  binary  from deserializer

此时,可以像其他任何表一样在 Hive 中使用支持 Avro 的表。

Hive 0.14 和更高版本

Hive 0.14开始,可以简单地通过在 DDL 语句中使用“ STORED AS AVRO”来创建 Avro 支持的表。 AvroSerDe 负责根据 Hive 表架构创建适当的 Avro 架构,这在 Hive 中的 Avro 可用性方面是一个巨大的胜利。

For example:

CREATE TABLE kst (
    string1 string,
    string2 string,
    int1 int,
    boolean1 boolean,
    long1 bigint,
    float1 float,
    double1 double,
    inner_record1 struct<int_in_inner_record1:int,string_in_inner_record1:string>,
    enum1 string,
    array1 array<string>,
    map1 map<string,string>,
    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<int_in_inner_record1:int,string_in_inner_record1:string> from deserializer
enum1   string  from deserializer
array1  array<string>   from deserializer
map1    map<string,string>      from deserializer
union1  uniontype<float,boolean,string> from deserializer
fixed1  binary  from deserializer
null1   void    from deserializer
unionnullint    int     from deserializer
bytes1  binary  from deserializer

将表写入 Avro 文件

AvroSerde 可以将任何 Hive 表序列化为 Avro 文件。这有效地使其成为 Any-Hive 型至 Avro 转换器。为了将表写入 Avro 文件,必须首先创建适当的 Avro 模式(Hive 0.14.0 及更高版本中除外,如下所述)。当前不支持“创建为选择类型”语句。

类型转换如上表中所述。对于不直接翻译的类型,需要牢记以下几点:

  • 可能为 null 的类型必须定义为该类型与 Avro 中的 Null 的并集. 如果未定义字段中的 null,则在保存期间会导致异常。无需更改 Hive 模式即可支持此功能,因为 Hive 中的所有字段都可以为 null。

  • Avro 字节类型应在 Hive 中定义为小整数列表。在保存过程中,AvroSerde 会将其转换为字节。

  • Avro 固定类型应在 Hive 中定义为小整数列表。 AvroSerde 将在保存过程中将其转换为“固定”。

  • 由于 Hive 没有枚举的概念,因此应该在 Hive 中将 Avro Enum 类型定义为字符串。确保表中仅存在有效的枚举值–尝试保存未定义的枚举将导致异常。

Hive 对于类型非常宽容:它将尝试将与提供的列匹配的任何值存储在新表的等效列位置中。例如,不对列名进行匹配。因此,查询编写器有责任确保目标列类型正确。如果不是,则 Avro 可以接受该类型,否则可能引发异常。这取决于类型的特定组合。

Example

考虑以下 Hive 表,该表涵盖了所有类型的 Hive 数据类型,使其成为一个很好的示例:

CREATE TABLE test_serializer(string1 STRING,
                             int1 INT,
                             tinyint1 TINYINT,
                             smallint1 SMALLINT,
                             bigint1 BIGINT,
                             boolean1 BOOLEAN,
                             float1 FLOAT,
                             double1 DOUBLE,
                             list1 ARRAY<STRING>,
                             map1 MAP<STRING,INT>,
                             struct1 STRUCT<sint:INT,sboolean:BOOLEAN,sstring:STRING>,
                             union1 uniontype<FLOAT, BOOLEAN, STRING>,
                             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 文件支持,例如:

为什么在那里4231001412341true42.4385.23423424alpha:beta:gammaEarth#42:Control#86:Bob#3117:true:Abe Linkedin0:3.141459BLUE72^A^B^C^A^B^C
another record9841019999999false99.890.00000009betaEarth#1011134:false:wazzup1:trueREDNULL^D^E^F^G^D^E^F
third record455102999999999true89.990.00000000000009alpha:gammaEarth#237:Bob#723102:false:BNL2:该回家了GREENNULL^H^G^H^I

然后您可以按照以下说明将其写到 Avro。

所有 Hive 版本

要将此表另存为 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 及更高版本

在 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<STRING>,
                     map1 MAP<STRING,INT>,
                     struct1 STRUCT<sint:INT,sboolean:BOOLEAN,sstring:STRING>,
                     union1 uniontype<FLOAT, BOOLEAN, STRING>,
                     enum1 STRING,
                     nullableint INT,
                     bytes1 BINARY,
                     fixed1 BINARY)
STORED AS AVRO;
INSERT OVERWRITE TABLE as_avro SELECT * FROM test_serializer;

Avro 文件 extensions

由 Hive 作业写入的文件是有效的 Avro 文件,但是,MapReduce 没有添加标准的.avroextensions。如果将这些文件复制出来,则可能需要使用.avro 重命名它们。

为表指定 Avro 模式

有三种方法可为 Avro 表提供读取器模式,所有方法都涉及 Serde 的参数。随着架构的 Developing,您可以通过更新表中的参数来更新这些值。

Use avro.schema.url

指定用于访问架构的 URL。对于 http 模式,这适用于测试和小型集群,但是由于将从作业中的每个任务中至少访问一次该模式,因此可以将作业快速转变为针对 URL 提供程序(Web 服务器,例如)。使用此参数进行测试以外的其他任何操作时,请务必小心。

该模式还可以指向 HDFS 上的某个位置,例如:hdfs:// your-nn:9000/path/to/avsc/file。然后,AvroSerde 将从 HDFS 读取文件,这应提供一次多次读取的弹性。请注意,serde 将从每个 Map 器读取此文件,因此,最好将模式文件的复制设置为较高的值,以便为 Reader 提供良好的局部性。模式文件本身应相对较小,因此不会给流程增加大量开销。

使用 schema.literal 并将架构嵌入到 create 语句中

您可以将模式直接嵌入到 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 语句中。

使用 avro.schema.literal 并将架构传递到脚本中

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 插入到引号中以正确处理模式中的空格。

不使用它们忽略 avro.schema.literal 或 avro.schema.url

Hive 无法提供一种轻松的方法来取消设置或删除属性。如果您希望从使用 URL 或架构切换为其他,请将要忽略的值设置为 none ,AvroSerde 会将其视为未设置。

HBase Integration

Hive 0.14.0 及更高版本支持通过将 Hro 列显示为 Hive 的结构来在 HBase 列中存储和查询 Avro 对象。这使 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 期望的序列中将不兼容的类型序列化时,最常见的期望是 exception。

FAQ

  • 在描述表或对表运行查询时,为什么会收到“错误错误错误错误错误错误错误错误**”和一条消息,以检查 avro.schema.literal 和 avro.schema.url?

Note

当 AvroSerde 找不到或解析 avro.schema.literal 或 avro.avro.schema.url 值提供的架构时,将返回此消息。它不能更加具体,因为 Hive 希望对 serde config 方法的所有调用都能成功,这意味着我们无法返回实际的异常。通过此消息发出错误 signal,该表将保持良好状态,并且可以通过调用 alter table T set TBLPROPERTIES 来更正错误的值。