[Hadoop] 使用Spark SQL来访问Hive里面的数据

By | 2018年12月20日

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wawa8899/article/details/82194004

1. 环境准备

1.1 安装Hive

1.2 安装Spark

1.3 拷贝hive的conf下的hive-site.xml到spark的conf目录下

[hadoop@hadoop000 ~]$ cd app/spark
[hadoop@hadoop000 spark]$ cp ~/app/hive-1.1.0-cdh5.7.0/conf/hive-site.xml conf/

1.4 准备MySQL驱动(如果用MySQL存储Hive metadata则需要)

[hadoop@hadoop000 ~]$ ls -ltr ~/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar
-rw-r--r--. 1 hadoop hadoop 1004838 Feb 26 21:28 /home/hadoop/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar
[hadoop@hadoop000 ~]$

 

2. Spark SQL使用交互式命令行来访问hive

2.1 使用Spark-shell交互式命令行来连接hive

[hadoop@hadoop000 ~]$ spark-shell --master local[2] --jars ~/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar

使用spark sql的api调用hive的命令,把结果展示出来

scala> spark.sql("show tables").show(false)
scala> spark.sql("select * from hive.emp").show(false)
scala> spark.sql("select * from hive.dept").show(false)
scala> spark.sql("select a.empno,a.name,b.dname from hive.emp a join hive.dept b on a.depno = b.deptno").show(false)

Spark SQL对hive表做join查询执行效率比hiveQL高很多。

 

2.2 使用spark-sql交互式命令行来连接hive

[hadoop@hadoop000 ~]$ spark-sql --master local[2] --jars ~/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar --driver-class-path ~/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar
#这里的--jars也可以不带

使用spark sql的api调用hive命令,把结果展示出来。这里的命令跟HiveQL命令一模一样。

spark-sql> select * from hive.emp;
spark-sql> select * from hive.dept;
spark-sql> select a.empno,a.name,b.dname from hive.emp a join hive.dept b on a.depno = b.deptno;

Spark的Web UI右上角的显示会随着连接方式的改变而改变

2.3 Cache使用

将emp表cache起来

spark-sql> cache table hive.emp;

然后再查询

spark-sql> select * from hive.emp;

在Spark Core中,cache是一个lazy的操作;但在spark SQL中,它是一个eager的操作。Web UI上可以看到cache的job。

cache后,emp表的input size比没cache要大(job#8 VS job#6)。

3. Spark SQL通过JDBC/ODBC连接HiveServer2来访问Hive里面的数据

启动一个Spark Thrift Server。ThriftServer就对应Hive里面的HiveServer2。

[hadoop@hadoop000 ~]$ app/spark/sbin/start-thriftserver.sh --master local[2] --jars ~/software/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46.jar

从启动日志文件里面可以看到,服务端口号10000

18/08/31 09:05:22 INFO ThriftCLIService: Starting ThriftBinaryCLIService on port 10000 with 5...500 worker threads

启动之后通过Spark Web UI http://192.168.1.8:4040/jobs/可以看到启动的状态(如果4040被占用,它会启动在4041端口)。

此时我们可以通过spark beeline客户端来连接它。

beeline -u jdbc:hive2://192.168.1.8:10000 -n hadoop
select * from hive.emp;

特别注意:如果机器上面既装了spark又装了hive,要区分开启动的是spark的beeline还是hive的beeline!

 

除此之外,也可以通过编程,使用JDBC/ODBC来连接Spark ThriftServer。

pom.xml添加hive依赖

    <dependency>
      <groupId>org.apache.hive</groupId>
      <artifactId>hive-jdbc</artifactId>
      <version>1.1.0-cdh5.7.0</version>
    </dependency>

SparkSQLClientAPP.scala

/**
  * 通过JDBC连接Spark SQL
  */

package com.data.d1

import java.sql.DriverManager

object SparkSQLClientApp {
  def main(args: Array[String]): Unit = {

    Class.forName("org.apache.hive.jdbc.HiveDriver")

    val conn = DriverManager.getConnection("jdbc:hive2://10.132.37.38:10000","hadoop","")
    val stmt = conn.prepareStatement("select product_id,product_name from product_info limit 3")
    val rs = stmt.executeQuery()
    while (rs.next()) {
      println("product_id:" + rs.getInt("product_id") + " product_name:" + rs.getString("product_name"))
    }

    rs.close()
    stmt.close()
    conn.close()
  }
}

JDBC连接时,用户名写hadoop,不需要写密码。

 

thriftserver和spark-sql或者spark-shell的区别在哪?

我们的ThriftServer也是一个Application,ThriftServer启动后可以7*24小时一直运行。其他应用可以JDBC/ODBC的方式去访问它。这样减少了服务每次启动时带来的资源消耗和时间成本。

工作中我们经常也需要把自己的application封装成一个http服务,服务启动时一次性请求资源,客户端调用服务时一个http请求就可以把结果拿回来,不用去重复申请资源。

(HUE,Zeeplin都是以这样一种方式来执行的)

 

 

4. 执行计划(84:54)

 

总结:

  • Spark SQL不仅仅是SQL,它还可以做很多事情。典型的,它可以处理文件系统或者是其他存储系统上的不同的文件。
  • 如何使用Spark SQL处理其他文件系统上的文件呢?接下来的博客里面会补充。
  • 对Spark SQL的一些误解一定要澄清:spark sql 并不需要hive,spark sql要想处理hive里面的数据,第一种方式是通过hive-site连过去,第二种方式也可以通过起一个hive metastore的服务来连接。hive里面有两个常用的服务,HiveServer2和MetaStore2。如果是把MetaStore服务起起来,就可以使用spark sql操作hive里的数据了。当然它们都是配置在hive-site里面的。第二种方式不需要使用hive-site,用代码来编程,直接把地址写成metastore的地址即可。
  • 使用
  • 如何在Web页面点一个按钮,来跑spark作业,这种需求不太现实。spark 是一个分布式离线计算框架,跟web 前台不直接发生关系,它一定是要定时执行的,而且一般不会立马产生结果能满足页面请求的需要。前端要访问,是直接去拿计算的结果,而不是把计算的步骤提交上去(job会阻塞)。通过页面按钮去触发提交一个spark任务是可以的,但是不要等待它的结果。

发表评论