Impala 使用Avro文件格式


Impala 支持使用其数据文件使用 Avro 文件格式的表。Impala 可以查询 Avro 表。在 Impala 1.4.0 及更高版本中,Impala 可以创建 Avro 表,但不能向其中插入数据。对于插入操作,使用 Hive,然后切换回 Impala 来运行查询。

文件类型

格式

压缩编解码器

Impala 可以创造吗?

Impala 可以插入吗?

Avro

结构化的

活泼,gzip,放气

是的,在 Impala 1.4.0 及更高版本中。在较低版本中,使用 Hive 创建表。

否。通过使用LOAD DATA已经采用正确格式的数据文件导入数据,或者INSERT在 Hive 中使用,然后在 Impala 中使用。 REFRESH table_name

创建 Avro 表

要使用 Avro 文件格式创建新表,请CREATE TABLE通过带有STORED AS AVRO子句的Impala或通过 Hive发出语句。如果通过 Impala 创建表,则必须包含与 Avro 架构中指定的字段匹配的列定义。使用 Hive,您可以省略列而只指定 Avro 架构。

在Impala 2.3及更高版本中,CREATE TABLEfor Avro 表可以包含 SQL 样式的列定义,而不是通过TBLPROPERTIES 子句指定 Avro 表示法。如果 SQL 列定义中指定的类型与基础类型之间存在任何不匹配,Impala 会发出警告消息;例如, anyTINYINT或 SMALLINTcolumn 被视为INT在基础 Avro 文件中,因此INT在 anyDESCRIBE或 SHOW CREATE TABLE输出中显示。

笔记:目前,Avro 表不能包含TIMESTAMP列。如果你需要存储日期和时间值在Avro的表格,作为一种解决方法,您可以使用一个 STRING值的表示,该值转换为 BIGINTUNIX_TIMESTAMP()功能或创建使用单独的日期和时间字段单独的数字列 EXTRACT()功能。

以下示例演示在 Impala 中创建 Avro 表,使用内联列规范或从存储在 HDFS 中的 JSON 文件中获取的列规范:

[localhost:21000] > CREATE TABLE avro_only_sql_columns
                  > (
                  >   id INT,
                  >   bool_col BOOLEAN,
                  >   tinyint_col TINYINT, /* Gets promoted to INT */
                  >   smallint_col SMALLINT, /* Gets promoted to INT */
                  >   int_col INT,
                  >   bigint_col BIGINT,
                  >   float_col FLOAT,
                  >   double_col DOUBLE,
                  >   date_string_col STRING,
                  >   string_col STRING
                  > )
                  > STORED AS AVRO;

[localhost:21000] > CREATE TABLE impala_avro_table
                  > (bool_col BOOLEAN, int_col INT, long_col BIGINT, float_col FLOAT, double_col DOUBLE, string_col STRING, nullable_int INT)
                  > STORED AS AVRO
                  > TBLPROPERTIES ('avro.schema.literal'='{
                  >    "name": "my_record",
                  >    "type": "record",
                  >    "fields": [
                  >       {"name":"bool_col", "type":"boolean"},
                  >       {"name":"int_col", "type":"int"},
                  >       {"name":"long_col", "type":"long"},
                  >       {"name":"float_col", "type":"float"},
                  >       {"name":"double_col", "type":"double"},
                  >       {"name":"string_col", "type":"string"},
                  >       {"name": "nullable_int", "type": ["null", "int"]}]}');

[localhost:21000] > CREATE TABLE avro_examples_of_all_types (
                  >     id INT,
                  >     bool_col BOOLEAN,
                  >     tinyint_col TINYINT,
                  >     smallint_col SMALLINT,
                  >     int_col INT,
                  >     bigint_col BIGINT,
                  >     float_col FLOAT,
                  >     double_col DOUBLE,
                  >     date_string_col STRING,
                  >     string_col STRING
                  >   )
                  >   STORED AS AVRO
                  >   TBLPROPERTIES ('avro.schema.url'='hdfs://localhost:8020/avro_schemas/alltypes.json');

以下示例演示在 Hive 中创建 Avro 表:

hive> CREATE TABLE hive_avro_table
    > 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'='{
    >    "name": "my_record",
    >    "type": "record",
    >    "fields": [
    >       {"name":"bool_col", "type":"boolean"},
    >       {"name":"int_col", "type":"int"},
    >       {"name":"long_col", "type":"long"},
    >       {"name":"float_col", "type":"float"},
    >       {"name":"double_col", "type":"double"},
    >       {"name":"string_col", "type":"string"},
    >       {"name": "nullable_int", "type": ["null", "int"]}]}');

记录的每个字段都成为表的一列。请注意,将忽略任何其他信息,例如记录名称。

注意: 对于可为空的 Avro 列,请确保将"null"条目放在实际类型名称之前。在 Impala 中,所有列都可以为空;Impala 目前没有NOT NULL条款。任何不可为空的属性仅在 Avro 端强制执行。

大多数列类型以相同的名称直接从 Avro 映射到 Impala。这些是需要考虑的例外和特殊情况:

  • DECIMAL类型在 Avro 中定义为属性设置为并具有指定精度和小数位数的BYTE类型 。 logicalType"decimal"
  • Avrolong类型映射到BIGINTImpala。

如果您通过 Hive 创建表,请切换回impala-shell并发出一条 语句。然后您可以通过impala-shell运行对该表的查询。 INVALIDATE METADATA table_name

在极少数情况下,Avro 架构和 Metastore 数据库中的列定义之间可能会发生不匹配。在Impala 2.3及更高版本中,Impala 在CREATE TABLE语句期间以及每次加载表的元数据时(例如, after INVALIDATE METADATA)检查此类不一致。Impala 使用以下规则来确定如何处理不匹配的列,这个过程称为模式协调:

  • 如果列数不匹配,Impala 将使用 Avro 架构中的列定义。
  • 如果列名或类型不匹配,Impala 将使用 Avro 架构中的列定义。因为Impala 中的a CHARorVARCHAR列映射到 Avro STRING,所以这种情况不被视为不匹配,并且该列被保留为CHARVARCHAR 在协调模式中。在Impala 2.7之前,此类CHARVARCHAR列的列名和注释也取自 SQL 列定义。在Impala 2.7及更高版本中,Avro 模式文件中的列名和注释优先用于此类列,并且SQL 列定义中仅保留CHARorVARCHAR类型。
  • ImpalaTIMESTAMP列定义映射到 AvroSTRINGSTRING 在协调模式中显示为 a ,因为 Avro 没有二进制TIMESTAMP表示。因此,没有 Avro 表可以有TIMESTAMP列;此限制与早期 Impala 版本中的相同。

复杂类型注意事项:虽然您可以使用Impala 2.3及更高版本中提供的复杂类型(ARRAYSTRUCT、 和 MAP)以这种文件格式创建表,但目前,Impala 只能在 Parquet 表中查询这些类型。 上述规则的一个例外是对包含复杂类型的 RCFile 表的查询。Impala 2.6及更高版本中允许此类查询 。COUNT(*)

在 Impala 中使用 Hive 创建的 Avro 表

如果你有一个通过 Hive 创建的 Avro 表,你可以在 Impala 中使用它,只要它只包含 Impala 兼容的数据类型。它不能包含:

  • 复杂类型:arraymaprecordstruct,union除了 or [supported_type,null][null,supported_type]
  • 该Avro的特定的类型enumbytesfixed

由于 Impala 和 Hive 共享相同的 Metastore 数据库,因此 Impala 可以直接访问在 Hive 中创建的表的表定义和数据。

如果您在 Hive 中创建了一个 Avro 表,INVALIDATE METADATA下次您通过impala-shell连接到 Impala 时发出一个。这是使 Impala 知道新表的一次性操作。您可以在连接到任何 Impala 节点时发出该语句,并且目录服务会将更改广播到所有其他 Impala 节点。

如果您通过 Hive 将新数据加载到 Avro 表中,通过 HiveLOAD DATA或 INSERT语句,或者通过手动将文件复制或移动到表的数据目录中,请在下次通过impala-shell连接到 Impala 时发出语句。您可以在连接到任何 Impala 节点时发出该语句,并且目录服务会将更改广播到所有其他 Impala 节点。如果您通过 Impala发出 声明,则不需要事后声明。 REFRESH table_nameLOAD DATAREFRESH

Impala 仅支持类型为booleanintlong、 floatdouble、 和 的字段string,或者这些类型的联合为空;例如,["string", "null"]。联合null本质上创建了一个可为空的类型。

通过 JSON 指定 Avro Schema

虽然您可以直接在CREATE TABLE语句中嵌入架构,如上所示,但 Hive 元存储中的列宽限制限制了您可以指定的架构长度。如果遇到长模式文字的问题,请尝试将模式存储为JSONHDFS 中的文件。使用类似于以下的表属性在 HDFS 中指定架构:

tblproperties ('avro.schema.url'='hdfs//your-name-node:port/path/to/schema.json');

将数据加载到 Avro 表中

目前,Impala 无法写入 Avro 数据文件。因此,Avro 表不能用作 ImpalaINSERT语句或CREATE TABLE AS SELECT.

要从另一个表复制数据,请INSERT通过 Hive发出任何语句。

如果您已经有 Avro 格式的数据文件,您也可以LOAD DATA在 Impala 或 Hive 中发出。Impala 可以将现有的 Avro 数据文件移动到 Avro 表中,它只是不能创建新的 Avro 数据文件。

为 Avro 表启用压缩

要为 Avro 表启用压缩,请在 Hive shell 中指定设置以启用压缩并指定编解码器,然后发出CREATE TABLE前面示例中的语句。Impala 支持Avro 表的snappydeflate编解码器。

例如:

hive> set hive.exec.compress.output=true;
hive> set avro.output.codec=snappy;

Impala 如何处理 Avro Schema Evolution

从 Impala 1.1 开始,Impala 可以处理采用模式演化的Avro 数据文件,其中同一个表中的不同数据文件使用略有不同的类型定义。(您将通过ALTER TABLE在 Hive shell 中发出一条语句来执行模式演化操作。)任何已更改列的旧类型和新类型必须兼容,例如,列可能int以 a开头,然后更改为 abigintfloat

与在当前impalad节点之外更改定义或添加数据的任何其他表一样, 如果 Avro 架构通过 Hive 修改,请确保 Impala 加载表的最新元数据。发出或 声明。 立即重新加载元数据,下次访问表时重新加载元数据。 REFRESH table_nameINVALIDATE METADATA table_nameREFRESHINVALIDATE METADATA

当查询期间未查阅 Avro 数据文件或列时,Impala 不会检查一致性。因此,如果您发出SELECT c1, c2 FROM t1,如果列c3以不兼容的方式更改,Impala 不会返回任何错误 。如果查询从某些分区检索数据而不是其他分区,Impala 不会检查未使用分区的数据文件。

在 Hive DDL 语句中,您可以指定avro.schema.literal表属性(如果架构定义很短)或avro.schema.url属性(如果架构定义很长,或者允许对定义进行方便的编辑)。

例如,在 Hive shell 中运行以下 SQL 代码会使用 Avro 文件格式创建一个表,并将一些示例数据放入其中:

CREATE TABLE avro_table (a string, b 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.literal'='{
    "type": "record",
    "name": "my_record",
    "fields": [
      {"name": "a", "type": "int"},
      {"name": "b", "type": "string"}
    ]}');

INSERT OVERWRITE TABLE avro_table SELECT 1, "avro" FROM functional.alltypes LIMIT 1;

创建 Avro 表并包含数据后,您可以通过impala-shell命令对其进行查询 :

[localhost:21000] > select * from avro_table;
+---+------+
| a | b    |
+---+------+
| 1 | avro |
+---+------+

现在在 Hive shell 中,您更改列的类型并添加一个具有默认值的新列:

-- Promote column "a" from INT to FLOAT (no need to update Avro schema)
ALTER TABLE avro_table CHANGE A A FLOAT;

-- Add column "c" with default
ALTER TABLE avro_table ADD COLUMNS (c int);
ALTER TABLE avro_table SET TBLPROPERTIES (
  'avro.schema.literal'='{
    "type": "record",
    "name": "my_record",
    "fields": [
      {"name": "a", "type": "int"},
      {"name": "b", "type": "string"},
      {"name": "c", "type": "int", "default": 10}
    ]}');

再次在impala-shell 中,您可以根据最新的架构定义查询 Avro 表。因为在 Impala 之外更改了表元数据,所以您REFRESH 首先发出一条语句,以便 Impala 拥有该表的最新元数据。

[localhost:21000] > refresh avro_table;
[localhost:21000] > select * from avro_table;
+---+------+----+
| a | b    | c  |
+---+------+----+
| 1 | avro | 10 |
+---+------+----+

Avro 表的数据类型注意事项

Avro 格式定义了一组数据类型,其名称与对应的 Impala 数据类型的名称不同。如果您使用其他 Hadoop 组件(例如 Pig 或 MapReduce)准备 Avro 文件,则可能需要使用 Avro 定义的类型名称。下图列出了 Avro 定义的类型和 Impala 中的等效类型。

原始类型:

Avro型

黑斑羚类型

细绳

细绳

细绳

字符

细绳

VARCHAR

情报局

情报局

布尔值

布尔值

LONG

大数据

漂浮

漂浮

双倍的

双倍的

Avro 规范允许字符串值最长为 2**64 字节。Avro 表的 Impala 查询使用 32 位整数来保存字符串长度。

在帕拉2.5和更高,帕拉截断 CHARVARCHAR值在表阿夫罗至(2 ** 31)-1字节。如果查询STRING在 Avro 表中遇到长于 (2**31)-1 字节的 值,则查询失败。在早期版本中,在 Avro 表中遇到如此长的值可能会导致崩溃。

逻辑类型:

Avro型

黑斑羚类型

字节注释

十进制

INT32 注释

日期

Impala 不支持以下 Avro 数据类型:RECORD、MAP、ARRAY、UNION、ENUM、FIXED、NULL

Impala Avro 表的查询性能

一般来说,Avro 表的查询性能比使用文本数据的表快,但比 Parquet 表慢。

在Impala 2.6及更高版本中,Impala 查询针对存储在 Amazon S3 中的文件进行了优化。对于使用文件格式的实木复合地板,ORC,RCFile,SequenceFile,Avro的,和未压缩文本因帕拉表中,设置 fs.s3a.block.size了在核心的site.xml 配置文件决定帕拉如何划分的读取数据文件的I / O工作。此配置设置以字节为单位指定。默认情况下,此值为 33554432 (32 MB),这意味着 Impala 将文件上的 S3 读取操作并行化,就好像它们由 32 MB 块组成一样。例如,如果您的 S3 查询主要访问由 MapReduce 或 Hive 编写的 Parquet 文件,则增加fs.s3a.block.size到 134217728 (128 MB) 以匹配这些文件的行组大小。如果大多数 S3 查询涉及 Impala 编写的 Parquet 文件,请增加到fs.s3a.block.size268435456 (256 MB) 以匹配 Impala 生成的行组大小。