本文简单的介绍了 Spark SQL 3.0 与 Hive 2.1的结合,包括安装配置,spark-sql的使用,spark thriftserver的使用及 spark thriftserver 日志信息的查看。

文中通过简单的案例串联起来了 spark thriftserver 和 hive的结合,有较强的参考价值。

0.解压spark3.0.1的包

将编译好的spark-3.0.1-bin-hadoop-3.0.0-cdh6.1.0.tgz 的软件包解压的指定目录 /data/soft/spark_3.0.1

export SPARK_3_0_1_HOME=/data/soft/spark_3.0.1
tar -zxvf spark-3.0.1-bin-hadoop-3.0.0-cdh6.1.0.tgz
mv spark-3.0.1-bin-hadoop-3.0.0-cdh6.1.0 spark_3.0.1

1.添加CDH环境配置

链接hadoop/hive相关的配置文件到 conf目录下

cd $SPARK_3_0_1_HOME/conf
 
ln -s /etc/hive/conf/hdfs-site.xml hdfs-site.xml
ln -s /etc/hive/conf/mapred-site.xml mapred-site.xml
ln -s /etc/hive/conf/yarn-site.xml yarn-site.xml
ln -s /etc/hive/conf/core-site.xml core-site.xml
ln -s /etc/hive/conf/hive-env.sh hive-env.sh
ln -s /etc/hive/conf/hive-site.xml hive-site.xml

2.添加spark配置

cd $SPARK_3_0_1_HOME/conf

2.1 spark-defaults.conf

cp spark-defaults.conf.template spark-defaults.conf

vim spark-defaults.conf

在配置文件底部添加下面的配置

# hive metastore的版本设置为 2.1.1
spark.sql.hive.metastore.version=2.1.1
# 引用 hive2.1.1 相关的jar包
spark.sql.hive.metastore.jars=/opt/cloudera/parcels/CDH/lib/hive/lib/*
# 设置 spark提交任务默认的 yarn 队列
spark.yarn.queue=root.analysis

2.2 spark-env.sh

cp spark-env.sh.template spark-env.sh

vim spark-env.sh

在配置文件底部添加下面的配置

export HADOOP_CONF_DIR=/etc/hadoop/conf # 添加 hadoop 配置文件的路径
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 -Dspark.history.retainedApplications=3 -Dspark.history.fs.logDirectory=hdfs://nameservice1/user/history/done_intermediate/spark3.0.1/eventlogs" # 添加 spark job history 相关参数 包括 web ui的端口 / 缓存的spark作业日志数目 / 日志的hdfs路径

2.3 log4j.properties

cp log4j.properties.template log4j.properties  # 复制log4j模板, 添加 默认的log4j配置

若有其他需要,可以自行修改。

2.4 spark-sql命令

vim $SPARK_3_0_1_HOME/bin/spark-sql

在头部添加SPARK_HOME配置,以避免使用 CDH 集群的 spark jar包

SPARK_HOME=/data/soft/spark_3.0.1

3.分发spark软件包

将配置好的spark软件包分发到 CDH 集群的其他节点上,以备后续应用使用

scp -r spark_3.0.1 root@cdh-datanode02:/data/soft/.
scp -r spark_3.0.1 root@cdh-datanode03:/data/soft/.
...

4. spark-sql 命令使用

# 进入到 spark3.0.1 的 bin目录
cd $SPARK_3_0_1_HOME/bin
# 运行 spark-sql命令
./spark-sql --master yarn --name spark-sql-test
-- 示例测试 sql:
-- 查看hive中所有的 database
show databases;
 
 
-- 查看default库中所有的 table 信息
show tables;
 
 
 
-- 简单的逻辑运算
select 1 + 1;
 
-- 使用spark sql函数 current_date();
select current_date();
 
 
-- 创建测试表 default.foo
create table default.foo(id string, amount bigint);
 
 
-- 向测试表中插入4条数据
insert into table default.foo values('1',1)
,('2',2)
,('3',3)
,('4',2);
 
 
-- 查看测试表中的记录数
select count(1) as cnt from foo;
 
 
-- 根据amount字段进行汇总 并按照 amount数量顺序排列
select amount, count(1) from foo group by amount order by amount desc;
 
 
-- 退出 spark-sql命令
exit;

5. spark thriftserver 使用

启动spark thriftserver

注意需要添加启动端口号的配置

cd $SPARK_3_0_1_HOME/sbin
./start-thriftserver.sh \
--master yarn \
--executor-memory 2048m \
--hiveconf hive.server2.thrift.port=10005

使用spark3.0.1 自带的beeline进行连接

cd $SPARK_3_0_1_HOME/bin
./beeline
!connect jdbc:hive2://cdh-datanode1:10005/default
 
 
# 出现弹框提示输入账号密码信息,由于没有添加鉴权,直接按enter即可
 
-- 创建测试表 student_info
create table default.student_info(
id bigint comment '学生id'
, name string comment '学生姓名'
, birthday string comment '出生日期 yyyy-MM-dd'
, class string comment '班级名称 xxyy xx年级 yy班'
)
comment '学生信息表'
stored as parquet;
 
-- 初始化测算表数据
insert into default.student_info values(1,'黄小明','2002-01-09','0302')
,(2,'王小刚','2001-06-03','0305')
,(3,'董小梅','2002-07-03','0302')
,(4,'杨小宝','2002-05-03','0301')
,(5,'周小龙','2002-04-23','0302')
,(6,'周小龙','2002-06-28','0304')
,(7,'方小玉','2000-09-28','0204');
 
-- 查询插入进去的数据
select id, name, birthday, class from default.student_info;
0: jdbc:hive2://cdh-datanode1:10005/default> select id, name, birthday, class from default.student_info;
+-----+-------+-------------+--------+
| id  | name  |  birthday   | class  |
+-----+-------+-------------+--------+
| 4   | 杨小宝   | 2002-05-03  | 0301   |
| 5   | 周小龙   | 2002-04-23  | 0302   |
| 6   | 周小龙   | 2002-06-28  | 0304   |
| 7   | 方小玉   | 2000-09-28  | 0204   |
| 1   | 黄小明   | 2002-01-09  | 0302   |
| 2   | 王小刚   | 2001-06-03  | 0305   |
| 3   | 董小梅   | 2002-07-03  | 0302   |
+-----+-------+-------------+--------+
7 rows selected (0.275 seconds)
 
-- 对测试表 student_info的一些操作
-- a.查看各个班级的人数
select class, count(1) from default.student_info group by class;
0: jdbc:hive2://cdh-datanode1:10005/default> select class, count(1) from default.student_info group by class;
+--------+-----------+
| class  | count(1)  |
+--------+-----------+
| 0204   | 1         |
| 0305   | 1         |
| 0304   | 1         |
| 0301   | 1         |
| 0302   | 3         |
+--------+-----------+
5 rows selected (0.816 seconds)
 
 
-- b.使用explain查看 a 的执行计划
explain select class, count(1) from default.student_info group by class;
 
 
0: jdbc:hive2://cdh-datanode1:10005/default> explain select class, count(1) from default.student_info group by class;
+----------------------------------------------------+
|                        plan                        |
+----------------------------------------------------+
| == Physical Plan ==
*(2) HashAggregate(keys=[class#9977], functions=[count(1)])
+- Exchange hashpartitioning(class#9977, 200), true, [id=#15603]
+- *(1) HashAggregate(keys=[class#9977], functions=[partial_count(1)])
+- *(1) ColumnarToRow
+- FileScan parquet default.student_info[class#9977] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[hdfs://cdh-namenode1:8020/user/hive/warehouse/student_info], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<class:string>
 
|
+----------------------------------------------------+
1 row selected (0.087 seconds)
 
 
-- c.查询班级人数最多的班级名称
select 
class
from default.student_info
group by class
order by count(1) desc
limit 1;
0: jdbc:hive2://cdh-datanode1:10005/default> select 
. . . . . . . . . . . . . . . . . . . . . .>     class
. . . . . . . . . . . . . . . . . . . . . .> from default.student_info
. . . . . . . . . . . . . . . . . . . . . .> group by class
. . . . . . . . . . . . . . . . . . . . . .> order by count(1) desc
. . . . . . . . . . . . . . . . . . . . . .> limit 1;
+--------+
| class  |
+--------+
| 0302   |
+--------+
1 row selected (0.757 seconds)
 
 
-- d.查看年龄最小的学生所在的班级
select
class
from default.student_info
order by birthday
limit 1;
 
0: jdbc:hive2://cdh-datanode1:10005/default> select
. . . . . . . . . . . . . . . . . . . . . .>     class
. . . . . . . . . . . . . . . . . . . . . .> from default.student_info
. . . . . . . . . . . . . . . . . . . . . .> order by birthday
. . . . . . . . . . . . . . . . . . . . . .> limit 1;
+--------+
| class  |
+--------+
| 0204   |
+--------+
1 row selected (0.202 seconds)
 
 
-- e.查看各个年级的总人数
select
count(1) as cnt
, substr(class,1,2) as grade
from default.student_info
group by substr(class,1,2);
 
 
0: jdbc:hive2://cdh-datanode1:10005/default> select
. . . . . . . . . . . . . . . . . . . . . .>     count(1) as cnt
. . . . . . . . . . . . . . . . . . . . . .>     , substr(class,1,2) as grade
. . . . . . . . . . . . . . . . . . . . . .> from default.student_info
. . . . . . . . . . . . . . . . . . . . . .> group by substr(class,1,2);
+------+--------+
| cnt  | grade  |
+------+--------+
| 6    | 03     |
| 1    | 02     |
+------+--------+
2 rows selected (0.752 seconds)
 
 
-- f.在同一年级中,给每个学生根据出生年月从年纪小到大编号
select
substr(class,1,2) as grade
, name
, birthday
, row_number() over(partition by substr(class,1,2) order by birthday desc) as rn
from default.student_info;
 
 
0: jdbc:hive2://cdh-datanode1:10005/default> select
. . . . . . . . . . . . . . . . . . . . . .>     substr(class,1,2) as grade
. . . . . . . . . . . . . . . . . . . . . .>     , name
. . . . . . . . . . . . . . . . . . . . . .>     , birthday
. . . . . . . . . . . . . . . . . . . . . .>     , row_number() over(partition by substr(class,1,2) order by birthday desc) as rn
. . . . . . . . . . . . . . . . . . . . . .> from default.student_info;
+--------+-------+-------------+-----+
| grade  | name  |  birthday   | rn  |
+--------+-------+-------------+-----+
| 03     | 董小梅   | 2002-07-03  | 1   |
| 03     | 周小龙   | 2002-06-28  | 2   |
| 03     | 杨小宝   | 2002-05-03  | 3   |
| 03     | 周小龙   | 2002-04-23  | 4   |
| 03     | 黄小明   | 2002-01-09  | 5   |
| 03     | 王小刚   | 2001-06-03  | 6   |
| 02     | 方小玉   | 2000-09-28  | 1   |
+--------+-------+-------------+-----+
7 rows selected (1.166 seconds)
 
 
-- g.查询同一姓名学生的信息
select
id
, name
, birthday
, class
from (
select
id
, name
, birthday
, class
, count(1) over(partition by name) as cnt
from default.student_info
) t
where t.cnt > 1
;
 
 
0: jdbc:hive2://cdh-datanode1:10005/default> select
. . . . . . . . . . . . . . . . . . . . . .>     id
. . . . . . . . . . . . . . . . . . . . . .>     , name
. . . . . . . . . . . . . . . . . . . . . .>     , birthday
. . . . . . . . . . . . . . . . . . . . . .>     , class
. . . . . . . . . . . . . . . . . . . . . .> from (
. . . . . . . . . . . . . . . . . . . . . .>     select
. . . . . . . . . . . . . . . . . . . . . .>         id
. . . . . . . . . . . . . . . . . . . . . .>         , name
. . . . . . . . . . . . . . . . . . . . . .>         , birthday
. . . . . . . . . . . . . . . . . . . . . .>         , class
. . . . . . . . . . . . . . . . . . . . . .>         , count(1) over(partition by name) as cnt
. . . . . . . . . . . . . . . . . . . . . .>     from default.student_info
. . . . . . . . . . . . . . . . . . . . . .> ) t
. . . . . . . . . . . . . . . . . . . . . .> where t.cnt > 1
. . . . . . . . . . . . . . . . . . . . . .> ;
+-----+-------+-------------+--------+
| id  | name  |  birthday   | class  |
+-----+-------+-------------+--------+
| 5   | 周小龙   | 2002-04-23  | 0302   |
| 6   | 周小龙   | 2002-06-28  | 0304   |
+-----+-------+-------------+--------+
2 rows selected (3.426 seconds)
 
 
-- 退出beeline
!quit

6. spark thriftserver日志查看

6.1通过Yarn Scheduler的Tracking UI 查看 Spark Thriftserver的执行日志

a.搜索 JDBC,找到 Spark Thriftserver 的 application信息

b.点击 ApplicationMaster查看日志

cdh如何升级spark cdh spark-sql_cdh如何升级spark

 

6.2 spark thriftserver 执行 sql 任务的日志页面

cdh如何升级spark cdh spark-sql_spark_02

主页显示了一些简单的统计信息,如启动spark thriftserver的 User(用户): root , Total Uptime(总共的启动时间): 26min, Scheduling Mode(任务调度的模式) FIFO, Completed Jobs(已经完成的作业) 8

从Completed Jobs列表中可以查看到

字段

字段说明

Job Id

作业id

Description

作业的描述信息,上面执行了sql语句,这里显示的就是sql信息, 点击 链接可以查看具体的作业日志信息。

Submitted

作业提交时间

Duration

作业持续时间

Stages:

Succeeded/Total

执行阶段统计:

成功的执行阶段数/总执行阶段数

Tasks(for all stages):

Succeeded/Total

任务数目统计(对于所有执行阶段)

成功执行的任务数/总任务数

6.3 作业详细信息

查看上面 job 7 的信息 

-- g.查询同一姓名学生的信息

select

id

, name

, birthday

class

from (

select

id

, name

, birthday

class

, count(1) over(partition by name) as cnt

from default.student_info

) t

where t.cnt > 1

;

即 这个sql的详细的详细信息,页面中显示的信息有:

字段

字段说明

Status

作业状态信息

Associated SQL Query

相关从查询sql语句,点击可以查询到 具体的sql执行各阶段依赖的信息以及

Parsed Logical Plan 解析逻辑执行计划

Analyzed Logical Plan 分析逻辑执行计划

Optimized Logical Plan 优化逻辑执行计划

Physical Plan 物理执行计划

Job Group

作业所在组

Completed Stages

完成的执行阶段数目

Event Timeline

事件时间线

DAG Visualiazation

各个执行阶段的依赖关系图(简图,点击 Associated SQL Query可以查看更加详细的信息)

cdh如何升级spark cdh spark-sql_sql_03

Completed Stages列表中显示的信息

字段

字段说明

Stage Id

执行阶段id

Description

执行阶段描述信息

Submitted

执行阶段提交时间

Duration

改执行阶段所持续的时间

Tasks:

Succeeded/Total

任务数目:

成功执行任务数/总任务数

Input

输入数据量统计

Output

输出数据量统计

Shuffle Read

Shuffle阶段读数据量统计

Shuffle Write

Shuffle阶段写数据量统计

6.4 Associated SQL Query 详细信息页面

这个页面包括的信息有

字段

字段说明

Submitted Time

作业提交时间

Duration

作业持续时间

Succeeded Jobs

成功的 job id

DAG Visualization

作业执行各个阶段的详细统计信息

Details

各个阶段的执行计划信息

cdh如何升级spark cdh spark-sql_spark_04

 

 

cdh如何升级spark cdh spark-sql_cdh如何升级spark_05

7.总结

本文提供了 spark 3.0 与 CDH Hive 2.1 结合的实战信息,属于入门级别的内容,即把整个流程跑通了,若要运用到生产实践中还需要进行一系列的优化,如spark sql各种参数调优, spark sql日志具体日志的意义,spark thriftserver ha 配置, 与调度工具结合等。