Hive文件格式(一)

AvroSerDe

AvroSerde文件格式可在 Hive 0.9.1 和更高版本中使用。

概述–从Hive与Avro的合作

AvroSerde允许用户以Hive表的形式读取或写入Avro数据。 AvroSerde的要点:

  • 从Avro架构推断Hive表的架构。从Hive 0.14开始,可以从Hive表模式中推断Avro模式。
  • 利用Avro的向后兼容性功能,根据指定的架构读取表中的所有Avro文件。
  • 支持任意嵌套的架构。
  • 将所有Avro数据类型转换为等效的Hive类型。大多数类型可以精确映射,但是某些Avro类型在Hive中不存在,而是由AvroSerde自动转换。
  • 了解压缩的Avro文件。
  • 将处理可空类型的 Avro 习惯用法透明地转换为Union[T, null]到 T 中,并在适当时返回 null。
  • 将任何Hive表写入Avro文件。
  • 在我们的ETL流程中,已经可靠地针对最复杂的Avro模式进行了工作。
  • 从Hive 0.14开始,可以使用Alter Table语句将列添加到Avro支持的Hive表中。

AvroSerde 已针对 Hive 0.9.1 及更高版本构建和测试,并在 Hive 0.13 和 0.14 时使用 Avro 1.7.5.

Hive 版本Avro Version
Hive 0.9.1Avro 1.5.3
Hive 0.10,0.11 和 0.12Avro 1.7.1
Hive 0.13 和 0.14Avro 1.7.5
Avro到Hive的类型转换

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

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

可以使用 AvroSerDe 在 Hive 中创建 Avro-backed 表。

Hive 版本

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

在这个 example 中,我们从网络服务器中提取 source-of-truth reader schema。提供 schema 的其他选项如下所述。

使用标准 Hive 操作将 Avro files 添加到数据库(或创建外部 table)。

此 table 可能会产生如下描述:

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

此时,table 可以在 Hive 中使用,就像任何其他 table 一样。

Hive 0.14 及更高版本

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

例如:

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;

此 table 可能会产生如下描述:

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 Bytes 类型应该在 Hive 中定义为tiny int列表。 AvroSerde 将在保存 process 期间将这些转换为字节。
  • Avro Fixed 类型应该在 Hive 中定义为tiny int列表。 AvroSerde 将在保存 process 期间将这些转换为固定。
  • Avro Enum 类型应该在 Hive 中定义为 strings,因为 Hive 没有枚举的概念。确保 table 中只存在有效的 enum 值 - 尝试保存 non-defined enum 将导致 exception。

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

示例

考虑以下 Hive table,它涵盖了所有类型的 Hive 数据类型,使其成为一个很好的 example:

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;

如果 table 由 csv 文件支持,例如:

why hello there4231001412341true42.4385.23423424alpha:beta:gammaEarth#42:Control#86:Bob#3117:true:Abe Linkedin0:3.141459BLUE72AB^CAB^C
another record9841019999999false99.890.00000009betaEarth#1011134:false:wazzup1:trueREDNULLDEFGDE^F
third record455102999999999true89.990.00000000000009alpha:gammaEarth#237:Bob#723102:false:BNL2:Time to go homeGREENNULL^HGH^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 schema。上面显示的将表另存为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 文件扩展名

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

为 table 指定 Avro schema

有三种方法可以为 Avro table 提供 reader schema,所有这些方法都涉及到 serde 的参数。随着 schema 的发展,您可以通过更新 table 中的参数来更新这些值。

使用 avro.schema.url

指定用于访问 schema 的 URL。对于 http 模式,这适用于测试和 small-scale 集群,但由于_jche 将至少从 job 中的每个任务访问一次,这可以快速将 job 转换为针对 URL 提供程序的 DDOS 攻击(例如 web 服务器) )。将此参数用于测试以外的任何其他操作时请小心。

schema 也可以指向 HDFS 上的某个位置,例如:hdfs://your-nn:9000/path/to/avsc/file。然后,AvroSerde 将从 HDFS 读取文件,该文件应立即提供针对多个读取的弹性。请注意,serde 将从每个映射器中读取此文件,因此将 schema 文件的复制转换为高值以便为 readers 提供良好的位置是一个很好的 idea。 schema 文件本身应该相对较小,因此这不会给 process 增加大量开销。

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

您可以将 schema 直接嵌入到 create 语句中。如果 schema 没有任何单引号(或者它们被适当地转义),这是有效的,因为 Hive 使用它来定义参数 value。例如:

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"}]
    }');

请注意,value 用单引号括起来,并粘贴到 create 语句中。

使用 avro.schema.literal 并将 schema 传递给脚本

Hive 可以执行简单的变量替换,您可以将嵌入在变量中的 schema 传递给脚本。请注意,要执行此操作,必须完全转义 schema(回车符转换为 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 已定义为转义的 schema value:

hive --hiveconf schema="${SCHEMA}" -f your_script_file.sql

请注意,$SCHEMA 被插入到引号中以正确处理 schema 中的空格。

使用 none 忽略 avro.schema.literal 或 avro.schema.url

Hive 不提供取消设置或删除 property 的简单方法。如果您希望从使用 URL 或 schema 切换到另一个,请将 to-be-ignored value 设置为none,AvroSerde 会将其视为未设置。

HBase Integration

Hive 0.14.0及更高版本支持通过在HBase列中将它们显示为Hive的结构来支持在Avro对象中存储和查询Avro对象。 这使Hive可以对允许深度构建的HBase数据执行临时分析。 在0.14.0之前,HBase Hive集成仅支持查询列中的原始数据类型。

如果出现问题

Hive 倾向于吞下在 job 提交之前发生的 AvroSerde 异常。为了使 Hive 更加冗长,可以使用* hive --hiveconf hive.root.logger=INFO,console *启动它,它会向 console 发送更多信息,并且可能包含 AvroSerde 试图获取的任何信息。如果 AvroSerde 在 MapReduce 期间遇到错误,则将在失败的任务 log 中提供堆栈跟踪,可以从 JobTracker 的 web 接口检查。 AvroSerde 仅发出 AvroSerdeException;请在任何错误报告中寻找包含这些错误信息的内容。尝试从Avro期望的序列中将不兼容的类型序列化时,最常见的是_exmon。

常见问题
  • 为什么在描述 table 或 running 查询 table 时,我会得到error-error-error-error-error-error-error和一条消息来检查 avro.schema.literal 和 avro.schema.url?

当 AvroSerde 无法查找或解析 avro.schema.literal 或 avro.avro.schema.url value 提供的 schema 时,会返回此消息。它无法更具体,因为 Hive 希望 serde 配置方法的所有 calls 都成功,这意味着我们无法 return 实际的 exception。通过此消息发出错误信号,table 保留在良好的 state 中,并且可以通过调用alter table T set TBLPROPERTIES来纠正错误的 value。

欢迎关注旺财AI

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值