这部分不是很难,只需要创建一个基本的maven项目,引入对应的mysql驱动和spark依赖项之后,将hive的配置文件放到resources目录下就可以了
1. 首先使用idea创建一个maven项目
2. 引入mysql驱动
在创建出来的maven项目中的pom文件中引入比赛环境对应的mysql数据库版本的驱动,这里使用5.7版本的mysql驱动作为示例
对应的坐标如下
<!-- 这里的version需要根据比赛具体的环境而定,如果是mysql8.0的版本,则需要引入8.0.xx的驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
3. 引入spark-core, spark-spl, spark-hive依赖
需要注意的是,Spark3.1.3版本到Spark3.0.0版本的spark都是使用的Scala都是2.12版本的,因此这些版本的spark依赖后面携带的都是2.12
而version的版本号是根据比赛环境的Spark版本而定的,假如比赛环境的Spark版本不是3.1.1版本的,那么就需要更改为比赛环境具体的Spark版本
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.12</artifactId>
<version>3.1.1</version>
</dependency>
将这些依赖项引入完毕后刷新一下maven项目,等待加载依赖项完毕
4. 指定的目录下拿到hive-site.xml文件
示例:文件位于/opt/apache-hive-2.3.4-bin/conf/
将文件复制到本地,然后将文件复制到resources目录下
5. 为项目增加Scala框架支持
点击项目目录,然后双击SHIFT,在出现的对象框中输入ADD, 在出现的提示中选择 ADD Frameworks Support,然后选择添加Scala框架支持,点击OK
可以看到此时已经可以创建Scala文件了
测试Scala环境,测试代码正常输出,并且hive的配置文件也正常出现在了运行的结果之中,表示环境是OK的
上面的配置为一个正常的maven项目,并且引入了Spark和MySQL的对应依赖,但是如果想要通过编写Scala代码使用Spark操作hive的方式处理离线数据,需要启动HDFS和YARN,并且需要启动Hive的metastore服务,如果想要使用jdbc的方式操作hive,则需要开启HiveServer2服务
下面是启动这些服务的示例Shell
启动HDFS和YARN的命令都需要在各自的Master节点上使用
# 启动HDFS
start-dfs.sh
# 启动YARN
start-yarn.sh
启动metastore服务
# 后台运行任务
nohup hive --service metastore >/dev/null 2>&1 &
启动HiveServer2服务
nohup hiveserver2 >/dev/null 2>&1 &
至此,所有的准备工作结束,这里我们编写一个测试程序
在刚刚创建出的maven项目中新建scala的object,编写下面的代码
package com.xi
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
object Test01 {
def main(args: Array[String]): Unit = {
// 这里需要和hdfs的超级用户的用户名保持一致
System.setProperty("HADOOP_USER_NAME", "root")
// 创建Spark连接
val conf = new SparkConf().setMaster("local[*]").setAppName("test01")
val spark = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()
spark.conf.set("hive.exec.dynamic.partition.mode", "nonstrict")
spark.sparkContext.setLogLevel("OFF")
// 读取mysql中的数据
val context = spark.read
.format("jdbc")
.option("Driver", "com.mysql.jdbc.Driver")
.option("url", "jdbc:mysql://192.168.88.102:3306/gmall") // 数据库的连接地址
.option("user", "root") // 数据库的用户名
.option("password", "000000") // 数据库的密码
.option("dbtable", "order_info") // 要读取的表名
.load()
// 给获取到的表连接创建临时视图并起一个别名方便查询
context.createTempView("order")
// 测试查询
spark.sql("select * from order").show()
// 关闭spark连接
spark.close()
}
}
这里可以看到,可以查询出结果, 证明从mysql环境中读取数据是没有问题的
下面测试向hive中写数据
在刚才的代码的基础上添加向hive中写入数据的代码,具体如下
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions.{current_date, date_format, date_sub}
object Test01 {
def main(args: Array[String]): Unit = {
// 这里需要和hdfs的超级用户的用户名保持一致
System.setProperty("HADOOP_USER_NAME", "root")
// 创建Spark连接
val conf = new SparkConf().setMaster("local[*]").setAppName("test01")
val spark = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()
spark.conf.set("hive.exec.dynamic.partition.mode", "nonstrict")
spark.sparkContext.setLogLevel("OFF")
// 读取mysql中的数据
val context = spark.read
.format("jdbc")
.option("Driver", "com.mysql.jdbc.Driver")
.option("url", "jdbc:mysql://192.168.88.102:3306/gmall") // 数据库的连接地址
.option("user", "root") // 数据库的用户名
.option("password", "000000") // 数据库的密码
.option("dbtable", "order_info") // 要读取的表名
.load()
// 给获取到的表连接创建临时视图并起一个别名方便查询
context.createTempView("order")
// 测试查询
val querySelect = spark.sql("select * from order")
querySelect.show()
// 添加测试分区字段
val result = querySelect
.withColumn("etldate", date_format(date_sub(current_date(), 1), "yyyyMMdd"))
result.show()
// 测试将结果写出到test库中的order_info表
result
.write // 写出数据
.format("hive") // 由于是从mysql中读取的数据,因此需要将这些数据的格式转化为hive的格式
.mode("append")
.partitionBy("etldate")
.saveAsTable("test.order_info")
spark.sql("show partitions test.order_info").show()
// 关闭spark连接
spark.close()
}
}
这里需要注意,由于HDFS的写入操作是需要权限的,并且这个用户和本地的Linu系统的用户可能并不一样,如果在第一行下面这段代码中设置的用户没有对HDFS中写入数据的权限,代码可能会报错,出现没有权限的错误
System.setProperty("HADOOP_USER_NAME", "root")
以下是因为没有写入文件的权限二导致的错误
可以看到,上面的结果中,查询操作是正常的,而写出操作出现了错误,具体的错误日志为
Exception in thread "main" org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: MetaException(message:Got exception: org.apache.hadoop.security.AccessControlException Permission denied: user=root, access=WRITE, inode="/user/hive/warehouse/test.db":atguigu:supergroup:drwxr-xr-x
因为root用户没有对/user/hive/warehouse/test.db中写出文件的权限,atguigu用户拥有对这个文件夹写出数据的权限,因此需要将上面的代码进行修改
System.setProperty("HADOOP_USER_NAME", "atguigu")
可以看到代码运行成功,现在到HDFS上对应的位置是否出现了分区
可以看到hdfs上已经有了对应的分区文件
使用Hive Cli查询写出的表的分区信息
查询表中的数据的根据total_amount字段倒序排序,查询前五行
查询成功,环境测试完毕,比赛时,这部分肯定不会测试的态度,这一段测试已经是数据抽取的内容了,比赛之前作为练习就可以了
还有几天就要比赛了,希望能拿个比较好的名次,加油!