大数据开发工程师-数据分析引擎之Impala-1


数据分析引擎之Impala-1

1 快速了解Impala

什么是Impala

1
2
3
4
5
6
7
咱们在最开始学习大数据的时候学到了MapReduce这个框架,他可以对海量数据进行分布式计算分析,但是由于需要一定学习成本,并且对非开发人员不够友好,所以后来出现了Hive这个数据分析工具。
Hive的优点是可以通过SQL直接计算分析HDFS中的海量数据,不需要写代码。
不过由于Hive底层引擎默认使用的是MapReduce,所以在Hive中提交的SQL任务的延迟度和计算效率相对一般。

在工作中我们希望能够在页面中输入一个SQL语句,点击查询按钮之后,可以快速查看结果,最好是能够在秒级别返回结果,这种数据分析需求也可以称之为即席查询。

此时如果使用Hive,基本上需要在分钟级别才能返回结果,因为Hive接收到用户在页面上输入的SQL之后,需要先把SQL转化为MapReduce、再把MapReduce任务提交到YARN集群中,这个流程就需要消耗几秒或者十几秒了。
1
2
3
4
5
6
7
8
9
10
11
此时就需要有一个可以支持低延迟,并且计算效率也比较高的数据分析引擎了,所以Impala就出现了。
Impala的出现主要就是为了解决Hive执行效率低下的问题。

所以MapReduce、Hive和Impala之间的发展历程是这样的:MapReduce->Hive->Impala。

官方一点的解释:
Impala是一个开源的基于内存的快速查询分析引擎。

他可以直接使用Hive的Metastore,也就是说Hive中创建的表,Impala可以直接使用;并且兼容HiveSQL,但是不是100%兼容,大部分的SQL语法都是兼容的。

下面我们来分析一下Impala的优点和缺点

Impala的优点

1
2
3
4
5
6
7
8
1:基于内存运算,中间结果不落盘,节省大量的I/O开销;因为在MapReduce任务中,Map阶段产生的中间结果需要先写磁盘,再通过Shuffle拷贝到Reduce阶段,所以会产生大量的I/O,因此计算效率不如Impala。
2:底层计算引擎由C++编写,通过LLVM统一编译运行,效率更高。LLVM是一个编译器。注意了,Impala底层的计算引擎没有使用大数据生态圈中的计算框架,它是自己单独实现的。
3:兼容HiveSQL语法,学习成本低,容易上手。ImpalaSQL支持SQL92标准,并具有自己的解析器和优化器。SQL92是数据库的一个ANSI标准,HiveSQL也支持SQL92标准。
4:兼容Hive的Metastore,可以直接使用Hive中的表。
5:支持数据本地化(Data Locality)特性,提高计算效率。其实就是说Impala支持数据本地计算,前提是impala的服务需要和HDFS的datanode节点部署在一起。
6:支持列式存储数据格式,可以和HBase整合。也就是说Impala可以通过SQL计算HBase中的数据。
7:支持多种文件格式,例如:TextFile、SequenceFile、RCFile、ORC和Parquet。其实只要是Hive支持的数据格式,目前Impala都是支持的。
8:支持ODBC/JDBC远程访问,这样就可以无缝对接到Web项目,在页面操作起来更方便。
1
2
这是Impala的一些优点。
当然了,没有绝对完美的技术框架,所以Impala也有一些缺点,下面我们来分析一下:

Impala的缺点

1
2
3
4
5
6
7
1:基于内存进行计算,对内存依赖性较大。基于内存计算,既是优点,也是缺点。
2:使用C++编写,意味着维护难度增加,相对而言,Java程序维护起来比较简单。
3:分区数量超过一万,性能严重下降,容易出现问题。主要还是因为它是基于内存计算,单个SQL任务计算的数据量过大,对内存依赖就很大了,所以容易出现问题。
4:基于Hive,与Hive共存亡。因为Impala需要使用Hive的Metastore来存储元数据信息。
5:稳定性不如Hive。主要也是因为Impala是基于内存的,所以稳定性相对来说一般。

这是Impala的一些缺点。

Impala + Hive

1
Impala和Hive之间的关系从这个图里面可以比较清晰的进行了解

image-20230619223624219

1
2
3
4
最底层是HDFS,接着是MapReduce、Hive对MapReduce做了封装,提供了SQL支持。
Hive的元数据信息存储在Metastore中,Metastore我们一般是使用MySQL。

Impala自己使用C++实现了一套分布式计算引擎,也可以直接操作HDFS中的数据,并且和Hive共享一个Metastore。

Impala三大核心组件

1
2
3
4
5
Impala架构中主要包含三大核心组件:

-Impala daemon:简称为impalad,它是Impala集群中的核心守护进程,需要在多个节点启动,一般会和DataNode节点部署在一起;他主要负责向Statestore保持通信,汇报工作。同时负责接收客户端的请求,执行查询,并把结果返回给客户端。
-Statestore daemon:简称为statestored,他主要负责收集集群中各个Impalad进程的资源信息、各节点健康状况、同步节点信息,以及负责Query的协调调度。
-Catalog daemon:简称为catalogd,他主要负责分发表的元数据信息到各个Impalad中,以及接收来自Statestore的所有请求。

Impala的整体运行架构

1
Impala的整体运行架构是这样的:

image-20230619224010407

1
2
这个图里面包含了客户端、Hive Metastore、HDFS NameNode、HDFS DataNode、HBase以及Impala中的Statestore、Catalog、Impalad这三个核心组件。
其中Hive Metastore是负责维护Impala元数据信息的,HDFS和HBase都是可以作为Impala底层数据存储的组件
1
2
3
4
5
6
7
客户端向Impala发送请求时的整个执行流程是这样的:
(1)客户端向某一个Impalad发送一个Query(SQL)。
(2)Impalad将Query解析为具体的Planner(执行计划), 然后交给当前机器的Coordinator(中心协调节点)。
(3)Coordinator根据Planner,通过本机的Executor执行,并转发给其他有数据的Impalad。
(4)多个Impalad的Executor之间会进行通信,可能需要一些数据的处理。
(5)各个Impalad的Executor执行完成后,会将结果返回给Coordinator。
(6)由Coordinator将汇聚的查询结果返回给客户端。

2 快速上手使用Impala

Impala的安装部署

1
2
3
4
5
单独安装Impala是不靠谱的想法,尽快忘了它!!!,因为单独安装Impala需要自己编译、编译的时候需要依赖很多外部依赖,以及一些依赖冲突的问题,所以不建议单独安装。

强烈推荐通过CDH平台安装Impala!!!CDH中集成的有Impala,安装非常方便,只需要点击下一步即可安装成功。

咱们本套课程的配套电子书中提供了CDH的安装部署步骤,其中CDH的版本是6.2.1,这个CDH版本中集成的Impala是3.2.0版本。
1
2
3
4
5
6
7
8
注意了:想要安装CDH,对机器配置有一定的要求,如果本地环境不允许的话,不建议去折腾了,意义不大。

自己本地没有CDH集群的话,针对Impala的内容大家暂时就无法在本地实操了,其实也不用特别担心,因为只要掌握了Hive的使用,想要使用Impala基本上可以直接上手。

咱们本次课程主要讲一些Impala和Hive的区别,这些内容大家前期有个概念,了解一下即可。
Impala的内容其实之前没有规划到课程中,后来考虑到个别同学反馈了,所以把这块内容扩展到课程中。

我的个人建议,Impala这块内容作为【选学】即可。
1
Impala集群节点的规划是这样的:

image-20230619224922160

1
2
3
4
5
6
7
8
Impala中的Catalog和Statestore进程所在的节点可以认为是主节点,建议把这两个进程部署在一起,因为他们两个之间需要经常通信。

Impala中的Daemon进程所在的节点可以认为是从节点,Daemon进程建议和Hadoop集群中的DataNode节点部署在一起,这样可以实现数据本地计算,提高计算效率。
Daemon进程可以根据需要部署多个。

想要使用Impala,是需要在CDH平台中安装的。

下面演示一下如何在CDH平台中安装Impala。

CDH平台中安装Impala

1
2
3
进入CM首页。

注意:需要先启动Cloudera Management Service和Cluster 1。
1
添加服务:

image-20230619225626270

1
选择Impala,然后点击继续按钮:

image-20230619225744765

1
2
3
4
如果cdh01主节点的内存足够使用的话,建议将StateStore和Catalog Server服务放到cdh01主节点中。
Impala Daemon服务放在从节点中。
当然了,也可以选择使用系统分配的,这样什么都不用改。
点击继续按钮:

image-20230619230300013

1
什么都不用改,点击继续按钮:

image-20230619230328291

1
等待状态变为 已完成,然后点击继续按钮:

image-20230619230400853

1
点击完成按钮即可:

image-20230619230421779

1
此时Impala服务已经安装成功了,但是还需要重启HDFS服务,点击重启按钮:

image-20230619230450678

1
确认更改信息,直接点击 重启过时服务按钮即可:

image-20230619230549712

1
注意:先选中【重新部署客户端配置】,然后再点击右下角的立即重启按钮:

image-20230619230610504

1
等待服务重启成功,状态变为 已完成,最后点击完成按钮即可。到这位置,Impala就安装好了。

image-20230619230636217

处理HDFS的权限问题

1
2
3
注意:由于我们现在默认使用的Linux中的root用户,所以在操作HDFS的时候会遇到一些权限问题,解决方案有2个:

1:关闭HDFS的权限校验。(这种方式简单、直接、生产环境不推荐,测试环境推荐)。

image-20230619225216524

image-20230619225257427

image-20230619225315978

image-20230619225343423

1
2
3
4
5
6
7
8
9
10
2:先在Linux添加supergroup组,把root用户添加到supergroup里,再同步权限到HDFS。
具体命令如下【这些命令需要在CDH集群中所有节点执行】。
(这种方式相对比较麻烦,但是更合理,生产环境下推荐,测试环境不推荐)。

# 添加supergroup组
groupadd supergroup
# root用户加入supergroup组
usermod -a -G supergroup root
# 同步系统的权限信息到HDFS
sudo -u hdfs hdfs dfsadmin -refreshUserToGroupsMappings
1
在测试环境建议使用第一种方式。

Impala的常见操作方式

1
2
3
4
5
Impala可以支持多种操作方式,在不同的应用场景中,可以选择不同的操作方式。

-在开发阶段,一般会使用impala-shell这个客户端命令行操作。
-如果想要在某一个Web项目中提供基于Impala的即席查询功能,那么需要使用JDBC代码的方式操作Impala。
-在日常查询使用的时候,特别是针对非开发人员,常见的是在Hue这种Web页面中进行操作,不需要连接Linux服务器,直接在浏览器页面中操作,非常方便。

impala-shell客户端命令行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
进入cdh01机器:
直接执行impala-shell脚本即可,因为CDH安装好Impala之后,会默认把Impala配置到环境变量中,所以它里面的脚本是可以在任意目录下使用的。

在cdh01中直接执行impala-shell脚本:
[root@cdh01 ~]# impala-shell
Starting Impala Shell without Kerberos authentication
Error connecting: TTransportException, Could not connect to cdh01:21000
***********************************************************************************
Welcome to the Impala shell.
(Impala Shell v3.2.0-cdh6.2.1 (525e372) built on Wed Sep 11 01:30:44 PDT 2019)

Press TAB twice to see a list of available commands.
***********************************************************************************
[Not connected] >
1
2
3
4
5
6
此时发现里面有报错信息,提示的是无法连接cdh01:21000。
21000端口对应的是impalad服务的端口,但是在cdh01上并没有启动impalad服务,所以默认连不上,impala-shell默认会连接当前节点上的impalad服务。
里面显示的也是[Not connected],这种情况下是无法操作Impala的。
因为在Impala中,只有连接到impalad所在的节点后才能执行查询操作,接受了连接的impalad节点将作为协调者运行查询任务。

为了解决这个问题,可以通过下面三种方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
第一种方法:
可以通过connect参数指定连接其它节点中的impalad服务。
[Not connected] > connect cdh02:21000;
Connection lost, reconnecting...
Error connecting: TTransportException, Could not connect to cdh01:21000
Opened TCP connection to cdh02:21000
Connected to cdh02:21000
Server version: impalad version 3.2.0-cdh6.2.1 RELEASE (build 525e372410dd2ce206e2ad0f21f57cae7380c0cb)
[cdh02:21000] default>

退出impala-shell客户端,使用ctrl+c无法强制退出:
可以使用quit或者exit。
[cdh02:21000] default> quit;
Goodbye root
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
第二种方法:
也可以在启动impala-shell客户端的时候通过-i参数指定连接其它节点中的impalad服务。
[root@cdh01 ~]# impala-shell -i cdh02:21000
Starting Impala Shell without Kerberos authentication
Opened TCP connection to cdh02:21000
Connected to cdh02:21000
Server version: impalad version 3.2.0-cdh6.2.1 RELEASE (build 525e372410dd2ce206e2ad0f21f57cae7380c0cb)
***********************************************************************************
Welcome to the Impala shell.
(Impala Shell v3.2.0-cdh6.2.1 (525e372) built on Wed Sep 11 01:30:44 PDT 2019)

After running a query, type SUMMARY to see a summary of where time was spent.
***********************************************************************************
[cdh02:21000] default>

退出impala-shell客户端:
[cdh02:21000] default> quit;
Goodbye root

注意:impalad服务的端口默认21000,如果没有修改的话,在使用-i和connect指定的时候,端口是可以省略不写的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
第三种方法:
在impalad服务所在的节点(cdh02 或者cdh03)执行使用impala-shell脚本即可

[root@cdh02 ~]# impala-shell
Starting Impala Shell without Kerberos authentication
Opened TCP connection to cdh02:21000
Connected to cdh02:21000
Server version: impalad version 3.2.0-cdh6.2.1 RELEASE (build 525e372410dd2ce206e2ad0f21f57cae7380c0cb)
***********************************************************************************
Welcome to the Impala shell.
(Impala Shell v3.2.0-cdh6.2.1 (525e372) built on Wed Sep 11 01:30:44 PDT 2019)

The '-B' command line flag turns off pretty-printing for query results. Use this
flag to remove formatting from results you want to save for later, or to benchmark
Impala.
***********************************************************************************
[cdh02:21000] default>
1
不过在实际工作中我们操作Impala一般都是在客户端节点操作的,所以还是需要通过-i或者connect参数指定impalad节点的。
-h / –help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在impala-shell脚本后面还可以指定一些高级命令,下面我们来看一些比较常见的:

-h / --help:这个属于帮助命令,可以查看impala-shell脚本后面都可以支持哪些命令,以及这些命令的含义。

[root@cdh01 ~]# impala-shell -h
Usage: impala_shell.py [options]

Options:
-h, --help show this help message and exit
-i IMPALAD, --impalad=IMPALAD
<host:port> of impalad to connect to
[default: cdh01:21000]
-b KERBEROS_HOST_FQDN, --kerberos_host_fqdn=KERBEROS_HOST_FQDN
If set, overrides the expected hostname of the
Impalad's kerberos service principal. impala-shell
will check that the server's principal matches this
hostname. This may be used when impalad is configured
to be accessed via a load-balancer, but it is desired
for impala-shell to talk to a specific impalad
directly. [default: none]
-q QUERY, --query=QUERY
Execute a query without the shell [default: none]
........
-v:查询当前Impala的版本。
1
2
[root@cdh01 ~]# impala-shell -v
Impala Shell v3.2.0-cdh6.2.1 (525e372) built on Wed Sep 11 01:30:44 PDT 2019
-B / –delimited:对Impala的查询结果进行格式化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
默认Impala中返回的结果数据是使用表格的样式格式化的,但是有时候我们想把impala查询的结果输出到文件中,便于后续其他的程序使用,这样就不希望把额外的表格输出到文件中了,只需要核心的数据内容即可。
先来看一下默认的格式:

[root@cdh01 ~]# impala-shell -i cdh02:21000
[cdh02:21000] default> create table im_t1(id int,name string);
[cdh02:21000] default> insert into im_t1(id,name) values(1,'zs');
[cdh02:21000] default> insert into im_t1(id,name) values(2,'ls');
[cdh02:21000] default> select * from im_t1;
Query: select * from im_t1
Query submitted at: 2022-08-16 15:52:27 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=5c47ba992fa4a26e:130a8aa600000000
+----+------+
| id | name |
+----+------+
| 1 | zs |
| 2 | ls |
+----+------+
Fetched 2 row(s) in 0.39s
[cdh02:21000] default> quit;
Goodbye root
1
2
3
4
5
6
7
8
9
10
11
12
13
14
此时可以发现结果数据会使用表格进行格式化,这样其实看起来是比较清晰的,但是这种数据格式不便于后期使用。

使用-B参数。

[root@cdh01 ~]# impala-shell -i cdh02:21000 -B
[cdh02:21000] default> select * from im_t1;
Query: select * from im_t1
Query submitted at: 2022-08-16 15:55:01 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=ef4080b39db068aa:9601e27400000000
1 zs
2 ls
Fetched 2 row(s) in 0.35s
[cdh02:21000] default> quit;
Goodbye root
1
此时可以看到结果数据就比较干净了,只有数据自身的内容,默认情况下字段之间的分隔符是制表符。
–output_delimiter:指定字段分隔符,默认\t
1
2
3
4
5
6
7
8
9
10
11
12
在使用-B对数据结果进行格式化的时候,如果想自定义字段分隔符,还需要使用这个参数。
使用逗号作为字段分隔符:
[root@cdh01 ~]# impala-shell -i cdh02:21000 -B --output_delimiter ','
[cdh02:21000] default> select * from im_t1;
Query: select * from im_t1
Query submitted at: 2022-08-16 15:57:41 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=c44e0ac395b5a6fd:831ea74700000000
2,ls
1,zs
Fetched 2 row(s) in 0.35s
[cdh02:21000] default> quit;
Goodbye root
-o / –output_file:将查询结果输出到指定的文件中
1
2
3
4
5
6
7
8
9
10
11
现在查询的结果还是输出在控制台中,想要将结果输出到文件中的话需要使用这个参数指定目标文件名。

注意:这里不能使用hdfs路径,只能使用本地路径。
[root@cdh01 ~]# impala-shell -i cdh02:21000 -B --output_delimiter ',' -o im_t1.dat
[cdh02:21000] default> select * from im_t1;
Query: select * from im_t1
Query submitted at: 2022-08-16 16:17:47 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=df43106813c0de1b:1dc183d000000000
Fetched 2 row(s) in 0.35s
[cdh02:21000] default> quit;
Goodbye root
1
2
3
4
5
此时发现在命令行中执行select语句是看不到返回结果的,因为这些结果数据会输出到im_t1.dat文件中。
到当前目录下查看一下im_t1.dat文件中的内容:
[root@cdh01 ~]# more im_t1.dat
1,zs
2,ls
1
但是这种方式用起来还是不方便,我们还需要先进入到impala-shell客户端里面之后才能执行查询命名,能不能在不进入impala-shell客户端的情况下实现这种需求呢?其实就是实现类似于hive -e这种效果。
-q / –query:指定查询语句
1
2
3
通过-q参数可以在命令行中指定sql语句,不需要进入impala-shell客户端里面,适合在脚本中封装impala sql语句。

在演示之前,先把im_t1.dat文件删掉,这样对比起来比较清晰。
1
[root@cdh01 ~]# rm -rf im_t1.dat
1
2
3
4
5
6
7
8
9
10
11
然后使用-q指定select查询语句。

[root@cdh01 ~]# impala-shell -i cdh02:21000 -B --output_delimiter ',' -q 'select * from im_t1' -o im_t1.dat
Starting Impala Shell without Kerberos authentication
Opened TCP connection to cdh02:21000
Connected to cdh02:21000
Server version: impalad version 3.2.0-cdh6.2.1 RELEASE (build 525e372410dd2ce206e2ad0f21f57cae7380c0cb)
Query: select * from im_t1
Query submitted at: 2022-08-16 16:25:43 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=2442747abbbf7f81:77c65fec00000000
Fetched 2 row(s) in 0.34s
1
2
3
4
5
6
7
8
查看im_t1.dat文件中的内容:
[root@cdh01 ~]# more im_t1.dat
1,zs
2,ls

此时这条impala sql命令就可以封装到shell脚本中定时调度了。
其实-q中指定的sql也可以使用insert into select这种形式的,这样就不需要使用-o指定输出文件路径信息了。
-q里面可以指定多条SQL语句,多条SQL语句之间使用分割(;)隔开即可。

JDBC访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
下面看一下如何使用JDBC代码操作Impala。

创建项目:db_impala
创建package:com.imooc.impala

向pom.xml中添加依赖,直接使用Hive的jdbc依赖即可。
<!-- Hive JDBC依赖 -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>

向resources目录中添加日志配置文件:log4j2.xml,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
创建类:ImpalaJdbcDemo

代码如下:
package com.imooc.impala;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
* JDBC代码操作Impala
*
* Created by xuwei
*/
public class ImpalaJdbcDemo {
public static void main(String[] args) throws Exception{
//指定jdbcurl链接,需要连接到impalad服务(cdh02或者cdh03)
String jdbcUrl = "jdbc:hive2://cdh03:21050/;auth=noSasl";
//获取链接
Connection conn = DriverManager.getConnection(jdbcUrl);

//获取Statement
Statement stmt = conn.createStatement();

//指定查询的sql
String sql = "select * from im_t1";
//执行sql
ResultSet res = stmt.executeQuery(sql);
//循环读取结果
while(res.next()){
System.out.println(res.getInt("id")+"\t"+res.getString("name"));
}

}
}

Hue访问

image-20230619232622289

image-20230619232649293

1
2
3
注意:第一次使用hue时,需要创建hue的账号,输入用户名和密码则会自动创建,这个账户将会是超级管理员账户。

账号创建好之后会进入这个界面。

image-20230619232756531

1
在查询按钮中可以选择Hue支持查询的组件,里面默认是没有Impala的。

image-20230619232830040

1
2
3
4
5
注意:默认CDH中提供的Hue里面是不支持访问Impala,需要在Hue配置中开启才可以。

下面到Hue中进行配置,增加对Impala的支持。

选中Impala、然后点击保存更改按钮。

image-20230619232857541

1
2
3
保存更改后,需要重启Hue,因为配置发生了变化。

点击重启过时服务按钮。

image-20230619232941817

image-20230619232952645

1
选中重新部署客户端配置,然后点击立即重启按钮即可。

image-20230619233024236

1
等待状态变为已完成,点击完成按钮即可。

image-20230619233039862

1
最终的效果是这样的:

image-20230619233056256

1
2
3
此时就可以选择Impala编辑器来操作Impala了。

在Hue中执行Impala SQL语句:

image-20230619233124191

image-20230619233143575

Impala的常见使用

1
Impala中的DDL和DML语句和Hive中的用法基本上是一样的,并且Impala中也支持内部表、外部表和分区表,下面我们来实际体验一下:

内部表的使用

1
2
3
4
5
6
7
8
9
10
11
12
创建内部表:im_inner_table

create table im_inner_table(
id int,
name string,
age int,
birthday timestamp
)row format delimited
fields terminated by '\t'
lines terminated by '\n';

注意:Impala中日期类型不支持Date,只支持Timestamp。Hive中这两种日期类型都支持。
desc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
查看表中的字段信息,以及详细建表语句。

[cdh02:21000] default> desc im_inner_table;
Query: describe im_inner_table
+----------+-----------+---------+
| name | type | comment |
+----------+-----------+---------+
| id | int | |
| name | string | |
| age | int | |
| birthday | timestamp | |
+----------+-----------+---------+
Fetched 4 row(s) in 0.06s
[cdh02:21000] default> show create table im_inner_table;
Query: show create table im_inner_table
+-------------------------------------------------------------------------------------------+
| result |
+-------------------------------------------------------------------------------------------+
| CREATE TABLE default.im_inner_table ( |
| id INT, |
| name STRING, |
| age INT, |
| birthday TIMESTAMP |
| ) |
| ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' |
| WITH SERDEPROPERTIES ('field.delim'='\t', 'line.delim'='\n', 'serialization.format'='\t') |
| STORED AS TEXTFILE |
| LOCATION 'hdfs://cdh01:8020/user/hive/warehouse/im_inner_table' |
| |
+-------------------------------------------------------------------------------------------+
Fetched 1 row(s) in 0.04s
[cdh02:21000] default>
load加载数据
1
2
3
4
5
6
7
8
9
10
表需要加载的数据文件为im_inner_table.dat,字段分隔符使用制表符,文件内容如下:
[root@cdh01 ~]# vi im_inner_table.dat
1 zs 18 2001-01-01 10:10:10
2 ls 17 2002-02-02 12:12:12
3 jack 19 2000-09-21 18:10:10

将此数据文件上传至hdfs中。
因为impala中在使用load data命令加载数据时不支持local参数,所以需要指定hdfs路径。
[root@cdh01 ~]# hdfs dfs -mkdir /data
[root@cdh01 ~]# hdfs dfs -put im_inner_table.dat /data
1
2
3
4
5
6
7
8
9
使用load data命令加载数据:
[cdh02:21000] default> load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_inner_table;
Query: load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_inner_table
ERROR: AnalysisException: Unable to LOAD DATA from hdfs://cdh01:8020/data/im_inner_table.dat because Impala does not have WRITE permissions on its parent directory hdfs://cdh01:8020/data

执行报错,提示impala针对/data目录没有写权限。

因为Impala是使用impala用户操作hdfs,所以没有权限,可以考虑修改hdfs中/data目录的读写权限。
[root@cdh01 ~]# hdfs dfs -chmod -R 777 /data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
再尝试加载数据:
[cdh02:21000] default> load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_inner_table;
Query: load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_inner_table
+----------------------------------------------------------+
| summary |
+----------------------------------------------------------+
| Loaded 1 file(s). Total files in destination location: 1 |
+----------------------------------------------------------+
Fetched 1 row(s) in 0.39s

提示数据加载成功。
查询表中的数据:
[cdh02:21000] default> select * from im_inner_table;
Query: select * from im_inner_table
Query submitted at: 2022-08-17 11:34:23 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=e241cccdd748bc56:e25e63af00000000
+----+------+-----+---------------------+
| id | name | age | birthday |
+----+------+-----+---------------------+
| 1 | zs | 18 | 2001-01-01 10:10:10 |
| 2 | ls | 17 | 2002-02-02 12:12:12 |
| 3 | jack | 19 | 2000-09-21 18:10:10 |
+----+------+-----+---------------------+
Fetched 3 row(s) in 0.57s
1
2
3
注意:impala中第一次查询一个表的时候会有点慢,后续查询就快了。

此时到HDFS中验证一下表中的数据文件:

image-20230619234100763

image-20230619234111203

1
2
Impala中的元数据会存储在Hive的Metastore中,所以我们到Hive对应的MySQL中查看一下表信息:
CDH中Hive的元数据库名称默认就是:metastore。

image-20230619234348237

1
查看表tbls中的数据:

image-20230619234421486

1
2
3
4
5
6
7
8
9
10
11
12
13
我们在impala中基于这个表执行一个group by功能,大家可以对比一下和Hive中执行的效率:
[cdh02:21000] default> select count(*),name from im_inner_table group by name;
Query: select count(*),name from im_inner_table group by name
Query submitted at: 2022-08-17 11:46:21 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=e43c81320d3157b:48ffbbfc00000000
+----------+------+
| count(*) | name |
+----------+------+
| 1 | ls |
| 1 | jack |
| 1 | zs |
+----------+------+
Fetched 3 row(s) in 0.46s
1
此时发现在impala中执行是很快的,只需要0.4秒左右。
1
下面在hive中执行,因为他们使用的是同一个元数据库,所以在hive中也可以看到这个表,并且也可以正常使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@cdh01 ~]# hive
hive> show tables;
OK
im_inner_table
im_t1
Time taken: 5.503 seconds, Fetched: 2 row(s)
hive> select count(*),name from im_inner_table group by name;
Query ID = root_20220817114954_acf8dfbe-e2c2-44ec-9e1a-f70436f53d51
Total jobs = 1
Launching Job 1 out of 1
Number of reduce tasks not specified. Estimated from input data size: 1
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
22/08/17 11:50:00 INFO client.RMProxy: Connecting to ResourceManager at cdh01/192.168.1.101:8032
22/08/17 11:50:01 INFO client.RMProxy: Connecting to ResourceManager at cdh01/192.168.1.101:8032
Starting Job = job_1660295939533_0003, Tracking URL = http://cdh01:8088/proxy/application_1660295939533_0003/
Kill Command = /opt/cloudera/parcels/CDH-6.2.1-1.cdh6.2.1.p0.1425774/lib/hadoop/bin/hadoop job -kill job_1660295939533_0003
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
2022-08-17 11:50:31,713 Stage-1 map = 0%, reduce = 0%
2022-08-17 11:50:51,427 Stage-1 map = 100%, reduce = 0%
2022-08-17 11:51:06,828 Stage-1 map = 100%, reduce = 100%, Cumulative CPU 19.05 sec
MapReduce Total cumulative CPU time: 19 seconds 50 msec
Ended Job = job_1660295939533_0003
MapReduce Jobs Launched:
Stage-Stage-1: Map: 1 Reduce: 1 Cumulative CPU: 19.05 sec HDFS Read: 8701 HDFS Write: 140 HDFS EC Read: 0 SUCCESS
Total MapReduce CPU Time Spent: 19 seconds 50 msec
OK
1 jack
1 ls
1 zs
Time taken: 75.01 seconds, Fetched: 3 row(s)
1
在hive中执行就比较慢了,大致需要75秒,而Impala执行只需要0.4秒(第一次大致需要0.57秒),所以他们之间的对比就非常明显了。

外部表的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
创建外部表:im_external_table
create external table im_external_table(
id int,
name string,
age int,
birthday timestamp
)row format delimited
fields terminated by '\t'
lines terminated by '\n'
location '/data/im_external_table';

表需要加载的数据文件为im_external_table.dat,字段分隔符使用制表符,文件内容如下:
[root@cdh01 ~]# vi im_external_table.dat
1 zs 18 2001-01-01 10:10:10
2 ls 17 2002-02-02 12:12:12
3 jack 19 2000-09-21 18:10:10

此时可以直接使用hdfs的put命令将数据文件上传到指定目录中,使用load data命令也可以。
[root@cdh01 ~]# hdfs dfs -put im_external_table.dat /data/im_external_table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
查询外部表中的数据:
[cdh02:21000] default> select * from im_external_table;
Query: select * from im_external_table
Query submitted at: 2022-08-17 15:07:09 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=b94b60c8dbdb4967:bbd4f2ff00000000
+----+------+-----+---------------------+
| id | name | age | birthday |
+----+------+-----+---------------------+
| 1 | zs | 18 | 2001-01-01 10:10:10 |
| 2 | ls | 17 | 2002-02-02 12:12:12 |
| 3 | jack | 19 | 2000-09-21 18:10:10 |
+----+------+-----+---------------------+
Fetched 3 row(s) in 4.35s
[cdh02:21000] default> select count(*),name from im_external_table group by name;
Query: select count(*),name from im_external_table group by name
Query submitted at: 2022-08-17 15:07:28 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=ae4cdaeafd180dbc:5bbda11b00000000
+----------+------+
| count(*) | name |
+----------+------+
| 1 | ls |
| 1 | jack |
| 1 | zs |
+----------+------+
Fetched 3 row(s) in 0.47s

分区表的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
分区表也可以分为外部分区表和内部分区表,在这里我们以外部分区表为例演示一下:

创建外部分区表:im_external_partition_table

create external table im_external_partition_table(
id int,
name string,
age int,
birthday timestamp
)partitioned by(dt string)
row format delimited
fields terminated by '\t'
lines terminated by '\n'
location '/data/im_external_partition_table';

注意:现在直接使用load data向分区中加载数据是会报错的,他会提示分区不存在。(Hive中这样执行是可以的。)

[cdh02:21000] default> load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_external_partition_table partition(dt='20220101');
Query: load data inpath 'hdfs://cdh01:8020/data/im_inner_table.dat' into table im_external_partition_table partition(dt='20220101')
ERROR: AnalysisException: Partition spec does not exist: (dt='20220101').
1
2
3
4
5
6
7
此时需要先到HDFS里面创建分区目录,再使用alter的方式添加分区,这种思路也是正常的操作流程,因为在实际工作中,外部分区表的数据是由专门的程序负责写入的。

手工在HDFS中创建分区表需要的分区目录,并且上传数据文件:
[root@cdh01 ~]# hdfs dfs -mkdir -p /data/im_external_partition_table/20220101
[root@cdh01 ~]# hdfs dfs -mkdir -p /data/im_external_partition_table/20220102
[root@cdh01 ~]# hdfs dfs -put im_external_table.dat /data/im_external_partition_table/20220101
[root@cdh01 ~]# hdfs dfs -put im_external_table.dat /data/im_external_partition_table/20220102
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在impala中添加分区。

[cdh02:21000] default> alter table im_external_partition_table add partition(dt='20220101') location '/data/im_external_partition_table/20220101';
Query: alter table im_external_partition_table add partition(dt='20220101') location '/data/im_external_partition_table/20220101'
+--------------------------------------------+
| summary |
+--------------------------------------------+
| New partition has been added to the table. |
+--------------------------------------------+
Fetched 1 row(s) in 6.16s
[cdh02:21000] default> alter table im_external_partition_table add partition(dt='20220102') location '/data/im_external_partition_table/20220102';
Query: alter table im_external_partition_table add partition(dt='20220102') location '/data/im_external_partition_table/20220102'
+--------------------------------------------+
| summary |
+--------------------------------------------+
| New partition has been added to the table. |
+--------------------------------------------+
Fetched 1 row(s) in 0.18s
1
2
3
4
5
6
7
8
9
10
11
查询表中的分区信息:
[cdh02:21000] default> show partitions im_external_partition_table;
Query: show partitions im_external_partition_table
+----------+-------+--------+------+--------------+-------------------+--------+-------------------+-------------------------------------------------------------+
| dt | #Rows | #Files | Size | Bytes Cached | Cache Replication | Format | Incremental stats | Location |
+----------+-------+--------+------+--------------+-------------------+--------+-------------------+-------------------------------------------------------------+
| 20220101 | -1 | 1 | 86B | NOT CACHED | NOT CACHED | TEXT | false | hdfs://cdh01:8020/data/im_external_partition_table/20220101 |
| 20220102 | -1 | 1 | 86B | NOT CACHED | NOT CACHED | TEXT | false | hdfs://cdh01:8020/data/im_external_partition_table/20220102 |
| Total | -1 | 2 | 172B | 0B | | | | |
+----------+-------+--------+------+--------------+-------------------+--------+-------------------+-------------------------------------------------------------+
Fetched 3 row(s) in 0.03s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
查询表中的数据:
[cdh02:21000] default> select * from im_external_partition_table;
Query: select * from im_external_partition_table
Query submitted at: 2022-08-17 16:08:40 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=1e486988e548514d:6c432b1700000000
+----+------+-----+---------------------+----------+
| id | name | age | birthday | dt |
+----+------+-----+---------------------+----------+
| 1 | zs | 18 | 2001-01-01 10:10:10 | 20220101 |
| 2 | ls | 17 | 2002-02-02 12:12:12 | 20220101 |
| 3 | jack | 19 | 2000-09-21 18:10:10 | 20220101 |
| 1 | zs | 18 | 2001-01-01 10:10:10 | 20220102 |
| 2 | ls | 17 | 2002-02-02 12:12:12 | 20220102 |
| 3 | jack | 19 | 2000-09-21 18:10:10 | 20220102 |
+----+------+-----+---------------------+----------+
Fetched 6 row(s) in 0.56s
[cdh02:21000] default> select * from im_external_partition_table where dt='20220101';
Query: select * from im_external_partition_table where dt='20220101'
Query submitted at: 2022-08-17 16:08:51 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=6040eadaa0e73718:2fe9f99000000000
+----+------+-----+---------------------+----------+
| id | name | age | birthday | dt |
+----+------+-----+---------------------+----------+
| 1 | zs | 18 | 2001-01-01 10:10:10 | 20220101 |
| 2 | ls | 17 | 2002-02-02 12:12:12 | 20220101 |
| 3 | jack | 19 | 2000-09-21 18:10:10 | 20220101 |
+----+------+-----+---------------------+----------+
Fetched 3 row(s) in 0.53s
[cdh02:21000] default> select name,count(*) from im_external_partition_table group by name;
Query: select name,count(*) from im_external_partition_table group by name
Query submitted at: 2022-08-17 16:09:28 (Coordinator: http://cdh02:25000)
Query progress can be monitored at: http://cdh02:25000/query_plan?query_id=cc4f17d9431288eb:304a855700000000
+------+----------+
| name | count(*) |
+------+----------+
| ls | 2 |
| jack | 2 |
| zs | 2 |
+------+----------+
Fetched 3 row(s) in 0.46s

本文标题:大数据开发工程师-数据分析引擎之Impala-1

文章作者:TTYONG

发布时间:2023年06月18日 - 23:06

最后更新:2023年06月19日 - 23:06

原始链接:http://tianyong.fun/%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%BC%95%E6%93%8E%E4%B9%8BImpala-1.html

许可协议: 转载请保留原文链接及作者。

多少都是爱
0%