Impala Azure Data Lake Store(ADLS) 结合使用


将Impala与Azure Data Lake Store(ADLS)结合使用

可以使用Impala查询驻留在Azure Data Lake Store(ADLS)文件系统上的数据。此功能允许方便地访问远程管理、可从任何地方访问并与各种基于云的服务集成的存储系统。Impala可以从ADLS查询任何支持的文件格式的文件。ADLS存储位置可以用于整个表或分区表中的单个分区。

默认的Impala表使用存储在HDFS上的数据文件,非常适合使用全表扫描的批量加载和查询。相比之下,针对ADLS数据的查询性能较差,这使得ADLS适合保存仅偶尔查询的“冷”数据,而更频繁访问的“热”数据驻留在HDFS中。在分区表中,您可以LOCATION为各个分区设置属性,将一些分区放在HDFS上,将其他分区放在ADLS上,通常取决于数据的年龄。

从Impala3.1开始,Impala支持ADLSGen2文件系统、AzureBlob文件系统(ABFS)。

先决条件

这些过程假定你已经设置了Azure帐户、配置了ADLS存储并使用适当的凭据配置了Hadoop集群以能够访问ADLS。

Impala SQL语句如何与ADLS配合使用

ImpalaSQL语句处理ADLS上的数据,如下所示。

在CREATETABLE语句或ALTERTABLE语句语句可以指定一个表驻留在ADLS文件系统通过使用以下ADLS前缀的一个LOCATION属性。

    • 对于ADLSGen1:adl://
    • 对于ADLSGen2:abfs://abfss://

ALTERTABLE还可以为LOCATION单个分区设置属性,使表中的一些数据驻留在ADLS上,同一个表中的其他数据驻留在HDFS上。

  • 有关使用信息请参阅为存储在ADLS上的数据创建Impala数据库、表和分区。
  • 一旦将表或分区指定为驻留在ADLS上,SELECT语句语句将从适当的存储层透明地访问数据文件。
  • 如果ADLS表是内部表,则在删除表时,DROPTABLE语句语句会从ADLS中删除相应的数据文件。
  • 该TRUNCATETABLE语句(黑斑羚2.3或更高版本)语句时,表将被截断,从ADLS始终删除相应的数据文件。
  • 在LOADDATA语句可以将驻留在HDFS到ADLS表中的数据文件。
  • 在INSERT语句,或CREATETABLEASSELECT在的形式CREATETABLE声明,可以从HDFS表或其他ADLS表将数据复制到一个ADLS表。

指定Impala凭据以访问ADLS中的数据

要允许Impala访问ADLS中的数据,请在core-site.xml文件中为以下配置设置指定值。

对于ADLSGen1:

<property>
   <name>dfs.adls.oauth2.access.token.provider.type</name>
   <value>ClientCredential</value>
</property>
<property>
   <name>dfs.adls.oauth2.client.id</name>
   <value>your_client_id</value>
</property>
<property>
   <name>dfs.adls.oauth2.credential</name>
   <value>your_client_secret</value>
</property>
<property>
   <name>dfs.adls.oauth2.refresh.url</name>
   <value>https://login.windows.net/your_azure_tenant_id/oauth2/token</value>
</property>

对于ADLSGen2:

<property>
    <name>fs.azure.account.auth.type</name>
    <value>OAuth</value>
  </property>
  <property>
    <name>fs.azure.account.oauth.provider.type</name>
    <value>org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider</value>
  </property>
  <property>
    <name>fs.azure.account.oauth2.client.id</name>
    <value>your_client_id</value>
  </property>
  <property>
    <name>fs.azure.account.oauth2.client.secret</name>
    <value>your_client_secret</value>
  </property>
  <property>
    <name>fs.azure.account.oauth2.client.endpoint</name>
    <value>https://login.microsoftonline.com/your_azure_tenant_id/oauth2/token</value>
  </property>

笔记:检查您的Hadoop发行版或集群管理工具是否支持以自动化方式在整个集群中填写和分发凭据。

指定凭据后,重新启动Impala和Hive服务。需要重新启动Hive,因为某些Impala查询(例如CREATETABLE语句)通过Hive元存储。

将数据加载到ADLS以进行Impala查询

如果您的ETL管道涉及将数据移动到ADLS然后通过Impala查询,您可以使用ImpalaDML语句来创建、移动或复制数据,或者使用与非Impala数据相同的数据加载技术。

对ADLS数据使用ImpalaDML语句

在Impala2.9及更高版本中,ImpalaDML语句(INSERTLOADDATACREATETABLEASSELECT)可以将数据写入驻留在Azure数据湖存储(ADLS)中的表或分区。Impala3.1及更高版本支持ADLSGen2。

CREATETABLEorALTERTABLE语句中,使用属性中adl://ADLSGen1和/abfs://abfss://ADLSGen2的前缀为表和分区指定ADLS位置LOCATION

如果您使用正常的ADLS传输机制而不是ImpalaDML语句将数据带入ADLS,请REFRESH在使用Impala查询ADLS数据之前为表发出一条语句。

在ADLS上手动将数据加载到Impala表中

作为替代方案,您可以使用Microsoft提供的方法将数据文件带入ADLS,以便通过Impala进行查询。

将数据文件上传到已映射到Impala表或分区的位置后,或者如果从此类位置删除ADLS中的文件,请发出语句以使Impala了解新的数据文件集。REFRESHtable_name

为ADLS上存储的数据创建Impala数据库、表和分区

Impala根据表或分区的LOCATION属性从ADLS读取表或分区的数据。在or语句的LOCATION子句中指定ADLS详细信息。该子句的语法是:CREATETABLEALTERTABLELOCATION对于ADLSGen1:

adl://account.azuredatalakestore.net/path/file

对于ADLSGen2:

abfs://container@account.dfs.core.windows.net/path/file

或者:

abfss://container@account.dfs.core.windows.net/path/file

container表示保存文件和文件夹的父位置,它是Azure存储Blob服务中的容器。

account是为您的存储帐户指定的名称。

笔记:

默认情况下,TLS是通过abfs://和启用的abfss://

当您设置该fs.azure.always.use.https=false属性时,使用禁用abfs://TLS,使用启用TLSabfss://

对于分区表,要么LOCATION为每个新分区指定一个单独的子句,要么LOCATION为该表指定一个基础并在ADLS中设置目录结构,以反映Impala分区表在HDFS中的结构方式。尽管严格来说,ADLS文件名没有目录路径,但Impala将ADLS文件名的/字符与包含目录的HDFS路径名相同。

要将未分区表或单个分区指向ADLS,请在ADLS中指定单个目录路径,该路径可以是任意目录。在ADLS中复制整个Impala分区表或数据库的结构需要更加小心,目录和子目录嵌套和命名以匹配HDFS中的等效目录树。如有必要,请考虑在HDFS中设置一个空的暂存区,并记录完整的目录结构,以便您可以在ADLS中复制它。

例如,以下会话创建一个分区表,其中只有一个分区驻留在ADLS上。2013年和2014年的分区位于HDFS上。2015年的分区包含一个LOCATION带有adl://URL的属性,因此指的是驻留在ADLS上的数据,位于store下的特定路径下impalademo

[localhost:21000] > create database db_on_hdfs;
[localhost:21000] > use db_on_hdfs;
[localhost:21000] > create table mostly_on_hdfs (x int) partitioned by (year int);
[localhost:21000] > alter table mostly_on_hdfs add partition (year=2013);
[localhost:21000] > alter table mostly_on_hdfs add partition (year=2014);
[localhost:21000] > alter table mostly_on_hdfs add partition (year=2015)
                  >   location 'adl://impalademo.azuredatalakestore.net/dir1/dir2/dir3/t1';

为方便处理包含存储在ADLS中的数据文件的多个表,您可以创建一个具有LOCATION指向ADLS路径的属性的数据库。指定表单的URL,如上所示。在该数据库内创建的任何表都会自动在数据库LOCATION属性指定的目录下创建目录。

以下会话创建一个数据库和两个完全驻留在ADLS上的分区表,一个由单个列分区,另一个由多个列分区。由于为数据库指定了LOCATION带有adl://URL的属性,因此该数据库中的表会在数据库目录下的ADLS上自动创建。要查看关联子目录的名称(包括分区键值),我们使用ADLS客户端工具检查目录结构在ADLS上的组织方式。例如,Impala分区目录month=1不包括前导零,这有时会出现在通过Hive创建的分区目录中。

[localhost:21000] > create database db_on_adls location 'adl://impalademo.azuredatalakestore.net/dir1/dir2/dir3';
[localhost:21000] > use db_on_adls;
[localhost:21000] > create table partitioned_on_adls (x int) partitioned by (year int);
[localhost:21000] > alter table partitioned_on_adls add partition (year=2013);
[localhost:21000] > alter table partitioned_on_adls add partition (year=2014);
[localhost:21000] > alter table partitioned_on_adls add partition (year=2015);
[localhost:21000] > ! hadoop fs -ls adl://impalademo.azuredatalakestore.net/dir1/dir2/dir3 --recursive;
2015-03-17 13:56:34          0 dir1/dir2/dir3/
2015-03-17 16:43:28          0 dir1/dir2/dir3/partitioned_on_adls/
2015-03-17 16:43:49          0 dir1/dir2/dir3/partitioned_on_adls/year=2013/
2015-03-17 16:43:53          0 dir1/dir2/dir3/partitioned_on_adls/year=2014/
2015-03-17 16:43:58          0 dir1/dir2/dir3/partitioned_on_adls/year=2015/
[localhost:21000] > create table partitioned_multiple_keys (x int)
                  >   partitioned by (year smallint, month tinyint, day tinyint);
[localhost:21000] > alter table partitioned_multiple_keys
                  >   add partition (year=2015,month=1,day=1);
[localhost:21000] > alter table partitioned_multiple_keys
                  >   add partition (year=2015,month=1,day=31);
[localhost:21000] > alter table partitioned_multiple_keys
                  >   add partition (year=2015,month=2,day=28);
[localhost:21000] > ! hadoop fs -ls adl://impalademo.azuredatalakestore.net/dir1/dir2/dir3 --recursive;
2015-03-17 13:56:34          0 dir1/dir2/dir3/
2015-03-17 16:47:13          0 dir1/dir2/dir3/partitioned_multiple_keys/
2015-03-17 16:47:44          0 dir1/dir2/dir3/partitioned_multiple_keys/year=2015/month=1/day=1/
2015-03-17 16:47:50          0 dir1/dir2/dir3/partitioned_multiple_keys/year=2015/month=1/day=31/
2015-03-17 16:47:57          0 dir1/dir2/dir3/partitioned_multiple_keys/year=2015/month=2/day=28/
2015-03-17 16:43:28          0 dir1/dir2/dir3/partitioned_on_adls/
2015-03-17 16:43:49          0 dir1/dir2/dir3/partitioned_on_adls/year=2013/
2015-03-17 16:43:53          0 dir1/dir2/dir3/partitioned_on_adls/year=2014/
2015-03-17 16:43:58          0 dir1/dir2/dir3/partitioned_on_adls/year=2015/

CREATEDATABASECREATETABLE,如果他们不存在语句创建相关的目录路径。您可以指定多个级别的目录,该CREATE语句会创建所有适当的级别,类似于使用mkdir-p.

使用标准的ADLS文件上传方法将数据文件实际放入正确的位置。您还可以在创建关联的Impala数据库或表之前放置目录路径和数据文件,并且在创建关联的数据库和表后,Impala会自动使用来自适当位置的数据。

您可以切换现有表或分区是否指向HDFS或ADLS中的数据。例如,如果您有一个Impala表或分区指向HDFS或ADLS中的数据文件,并且您稍后将这些数据文件传输到其他文件系统,请使用ALTERTABLE语句调整LOCATION相应表或分区的属性以反映该更改。这种位置切换技术对于具有自定义LOCATION属性的整个数据库并不实用。

位于ADLS上的内部和外部表

与位于HDFS存储上的表一样,您可以分别使用语法CREATETABLE或将基于ADLS的表指定为内部(由Impala管理)或外部表CREATEEXTERNALTABLE。删除内部表时,与该表关联的文件将被删除,即使它们位于ADLS存储上。当您删除外部表时,与该表关联的文件将单独保留,并且仍可供其他工具或组件访问。

如果ADLS上的数据旨在长期保存并由除Impala之外的其他工具访问,请使用CREATEEXTERNALTABLE语法创建任何关联的ADLS表,以便在删除表时不会从ADLS中删除文件。

如果ADLS上的数据只需要Impala查询,并且在Impala工作流完成后可以安全丢弃,请使用CREATETABLE语法创建关联的ADLS表,这样删除表也会删除ADLS上的相应数据文件。

例如,此会话在ADLS中创建一个表,其列布局与HDFS中的表相同,然后检查ADLS表并从中查询一些数据。ADLS中的表在数据、表和列统计信息以及其他表属性的预期文件格式方面与HDFS中的表相同。它不是HDFS表的唯一指示是属性中的adl://URLLOCATION。许多数据文件可以驻留在ADLS目录中,它们的组合内容构成了表数据。由于本示例中的数据是在创建表后上传的,因此一条REFRESH语句会提示Impala更新其有关数据文件的缓存信息。

[localhost:21000] > create table usa_cities_adls like usa_cities location 'adl://impalademo.azuredatalakestore.net/usa_cities';
[localhost:21000] > desc usa_cities_adls;
+-------+----------+---------+
| name  | type     | comment |
+-------+----------+---------+
| id    | smallint |         |
| city  | string   |         |
| state | string   |         |
+-------+----------+---------+
-- Now from a web browser, upload the same data file(s) to ADLS as in the HDFS table,
-- under the relevant store and path. If you already have the data in ADLS, you would
-- point the table LOCATION at an existing path.
[localhost:21000] > refresh usa_cities_adls;
[localhost:21000] > select count(*) from usa_cities_adls;
+----------+
| count(*) |
+----------+
| 289      |
+----------+
[localhost:21000] > select distinct state from sample_data_adls limit 5;
+----------------------+
| state                |
+----------------------+
| Louisiana            |
| Minnesota            |
| Georgia              |
| Alaska               |
| Ohio                 |
+----------------------+
[localhost:21000] > desc formatted usa_cities_adls;
+------------------------------+----------------------------------------------------+---------+
| name                         | type                                               | comment |
+------------------------------+----------------------------------------------------+---------+
| # col_name                   | data_type                                          | comment |
|                              | NULL                                               | NULL    |
| id                           | smallint                                           | NULL    |
| city                         | string                                             | NULL    |
| state                        | string                                             | NULL    |
|                              | NULL                                               | NULL    |
| # Detailed Table Information | NULL                                               | NULL    |
| Database:                    | adls_testing                                       | NULL    |
| Owner:                       | jrussell                                           | NULL    |
| CreateTime:                  | Mon Mar 16 11:36:25 PDT 2017                       | NULL    |
| LastAccessTime:              | UNKNOWN                                            | NULL    |
| Protect Mode:                | None                                               | NULL    |
| Retention:                   | 0                                                  | NULL    |
| Location:                    | adl://impalademo.azuredatalakestore.net/usa_cities | NULL    |
| Table Type:                  | MANAGED_TABLE                                      | NULL    |
...
+------------------------------+----------------------------------------------------+---------+

在本例中,我们已经将一个包含一百万行数据的Parquet文件上传到ADLS上商店sample_data下的目录impalademo。此会话创建一个表,其中包含指向ADLS中相应位置的匹配列设置,然后查询该表。因为在创建表时数据已经在ADLS上,所以不需要任何REFRESH语句。

[localhost:21000] > create table sample_data_adls
                  > (id int, id bigint, val int, zerofill string,
                  > name string, assertion boolean, city string, state string)
                  > stored as parquet location 'adl://impalademo.azuredatalakestore.net/sample_data';
[localhost:21000] > select count(*) from sample_data_adls;
+----------+
| count(*) |
+----------+
| 1000000  |
+----------+
[localhost:21000] > select count(*) howmany, assertion from sample_data_adls group by assertion;
+---------+-----------+
| howmany | assertion |
+---------+-----------+
| 667149  | true      |
| 332851  | false     |
+---------+-----------+

为存储在ADLS上的数据运行和调整Impala查询

LOCATION在表或分区级别设置适当的属性后,您查询ADLS中存储的数据与HDFS或HBase中存储的数据完全相同:

  • 针对ADLS数据的查询支持与HDFS数据相同的所有文件格式。
  • 表可以是未分区的或分区的。对于分区表,要么在ADLS中手动构建对应于表示分区键值的HDFS目录的路径,要么用于在ADLSALTERTABLE...ADDPARTITION中设置适当的路径。
  • HDFS、Kudu、HBase表可以连接到ADLS表,也可以相互连接ADLS表。
  • 无论数据是在HDFS中还是在ADLS中,使用Ranger框架来控制对数据库、表或列的访问的授权都是一样的。
  • 该catalogd守护程序都HDFS和ADLS表缓存元数据。使用REFRESHINVALIDATEMETADATA用于ADLS表中,你会发出HDFS表这些语句相同的情况。
  • 针对ADLS表的查询受制于与HDFS表相同类型的准入控制和资源管理。
  • ADLS表的元数据存储在与HDFS表相同的Metastore数据库中。
  • 您可以设置引用ADLS表的视图,与HDFS表相同。
  • COMPUTESTATSSHOWTABLESTATSSHOWCOLUMNSTATS报表工作ADLS表也。

了解和调整ADLS数据的Impala查询性能

尽管Impala查询ADLS中存储的数据的性能可能低于查询HDFS中存储的等效数据的性能,但您仍然可以进行一些调整。以下是可用于解释针对ADLS数据查询的解释计划和配置文件的技术,以及为此类查询实现最佳性能的技巧。

在其他条件相同的情况下,针对ADLS而非HDFS上的数据运行的查询的性能预计会较低。的实际力学SELECT当数据在ADLS中时,语句有些不同。虽然工作仍然分布在集群的数据节点上,但Impala可能会以不同的方式并行分布式查询的工作,以处理HDFS和ADLS上的数据。ADLS没有与HDFS相同的块概念,因此Impala使用启发式方法来确定如何拆分大型ADLS文件以进行并行处理。因为所有主机都可以以相同的效率访问任何ADLS数据文件,所以工作分配可能与HDFS数据不同,HDFS数据是由包含适当块副本的主机使用短路本地读取来物理读取数据块的。尽管读取ADLS数据的I/O可能均匀分布在集群的主机上,

因为ADLS不像HDFS那样公开数据文件的块大小,所以任何ImpalaINSERTCREATETABLEASSELECT语句都使用PARQUET_FILE_SIZE查询选项设置来定义Parquet数据文件的大小。(对于Parquet表,使用大块大小比使用其他文件格式的表更重要。)

在优化复杂查询的方面(例如连接顺序)时,Impala以相同的方式处理HDFS和ADLS上的表。因此,对于ADLS表和HDFS表遵循所有相同的调整建议,例如使用COMPUTESTATS语句来帮助Impala构建行计数和基数的准确估计。

在查询配置文件报告中BytesReadLocalBytesReadShortCircuitBytesReadDataNodeCached、和的数字为BytesReadRemoteUnexpected空,因为这些指标来自HDFS。如果您确实看到任何迹象表明对ADLS表的查询执行了“远程读取”操作,请不要惊慌。这是意料之中的,因为根据定义,ADLS表的所有I/O都涉及远程读取。

对ADLS的Impala支持的限制

Impala要求集群的默认文件系统是HDFS。您不能将ADLS用作集群中的唯一文件系统。

尽管ADLS通常用于存储JSON格式的数据,但当前Impala对ADLS的支持不包括直接查询JSON数据。如果您有JSON格式的数据,您可以准备该数据的扁平版本,作为ETL周期的一部分供Impala查询。

您不能对ALTERTABLE...SETCACHED位于ADLS中的表或分区使用该语句。

将Impala与ADLS结合使用的最佳实践

以下指南代表了从在ADLS上使用Impala进行测试和实际经验得出的最佳实践:

  • 对ADLS位置的任何引用都必须是完全限定的。(当ADLS未指定为默认文件系统时,此规则适用。)
  • 为impalad设置任何适当的配置设置。