一、SparkSQL历史
1、定义
Spark SQL is Apache Spark's module for working with structured data.
Spark SQL是用于处理结构化数据的Apache Spark模块。
2、去IOE
它是阿里巴巴造出的概念。其本意是,在阿里巴巴的IT架构中,去掉IBM的小型机、Oracle数据库、EMC存储设备,代之以自己在开源软件基础上开发的系统。
3、SQL前提
(1)schema作用到文件中
(2)select ... from table where
4、SQL on Hadoop
(1) Hive
最原始的解决方案,稳定性最高,但是慢
(2)Impala
和Hive共享metastore
(3)persto
(4)Spark-Shark(Spark1.0之前)
底层就是将SQL翻译成Spark作业,Hive跑在Spark之上,与Hive的兼容性不是很理想
(5)drill
(6)Phoenix
HBase不支持SQL查询,要用到Phoenix
5、Hive on Spark
Hive可以执行在MapReduce、Tez、Spark之上
6、Hive on Spark与Spark SQL的区别
Hive on Spark就是计算引擎使用Spark,运用场景会多一些,但是不稳定,而且实际上它是Hive的应用,不能与Spark的其他组件搭配使用,需要落地之后再加载,浪费资源。
二、Spark SQL
1、特性
(1)集成性
Seamlessly mix SQL queries with Spark programs.
将SQL查询与Spark程序无缝混合。
Spark SQL lets you query structured data inside Spark programs, using either SQL or a familiar DataFrame API. Usable in Java, Scala, Python and R.
Spark API:
SQL/DataFrame/Dataset
(2)统一数据存取
跟drill一样,可以访问不同的数据源,然后把结果放在spark临时表。
Connect to any data source the same way.
连接数据源通过相同的方式。
DataFrames and SQL provide a common way to access a variety of data sources, including Hive, Avro, Parquet, ORC, JSON, and JDBC. You can even join data across these sources.
DataFrames and SQL provide a common way to access a variety of data sources, including Hive, Avro, Parquet, ORC, JSON, and JDBC. You can even join data across these sources.
数据框架和SQL提供了访问各种数据源的通用方法,包括Hive、Avro、Parquet、ORC、JSON和JDBC。您甚至可以跨数据源联接数据(join)。
(3)集成Hive
Run SQL or HiveQL queries on existing warehouses.
在现有仓库上运行SQL或HiveQL查询,还可以使用已经存在的Hive的metastores,SerDes,andUDFS。
(4)Standard Connectivity
A server mode provides industry standard JDBC and ODBC connectivity for business intelligence tools.
一个服务器模式为商业智能工具提供行业标准JDBC和ODBC连接。
类似HiveServer2,Spark也有这样的server:
start-thriftserver.sh
所以可以直接用JDBC
(5)不仅只是SQL但是超出SQL
因为SparkSQL不仅处理数据,还可以处理文件,联合其他数据源,还可以使用各种API
总结:
Spark需要hadoop吗?
不需要,hadoop的hdfs和yarn,spark可以不跑在yarn上,也不一定要把数据写到hdfs上。
Spark需要Hive吗?
不需要,只要有metastore服务就行,能存元数据。metastore可以在其他节点起,然后spark只要在hive-site.xml里配置metastore的地址(thrift://…),这样就能做统一的元数据管理。
2、扩展
ETL(将数据从来源端经过抽取(extract)、交互转换(transform)、加载(load)至目的端的过程。):DataSource API,版本V1 V2
3、Spark SQL架构
Frontend Catalyst Spark SQL核心 Backend
AST抽象语法树/SQL 处理SQL的
三、搭建SparkSQL
1、所需环境
(1)Spark编译的时候要加上 -p Hive
(2)复制hive-site.xml到spark-conf,jdbc连接的数据库要填好。之后spark就默认对配置文件指定的数据库进行操作。
(3)MySQL驱动,通过spark-shell --jars提交
./spark-shell --master local[2] --jars /opt/lib/mysql-connector-java-5.1.47.jar
(4)先启动MySQL,Hadoop,取消safemode,启动Hive。
搭建成功
四、SparkSQL
1、创建dept、导数据
create table dept(
deptno int, dname string, loc string
)row format delimited fields terminated by '\t';
load data local inpath '/data/dept.txt' overwrite into table dept;
2、将MySQL的数据(已经有emp表和数据,只是我懒得再造数据,就试试用sqoop解决我的问题)导入Hive的emp表
create table emp
(empno int, ename string, job string, mgr int, hiredate string, salary double, comm double, deptno int)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
sqoop import \
--connect jdbc:mysql://localhost:3306/hbinz001 \
--username root --password 123456 \
--table emp -m 2 \
--mapreduce-job-name FromMySQLToHive \
--delete-target-dir \
--hive-database default \
--hive-table emp \
--fields-terminated-by '\t' \
--hive-overwrite \
--hive-import
注意sqoop的代码顺序,最后再import到Hive.
3、Hive、Sparksql之间join的对比
Hive:select e.empno,e.ename,d.dname from emp e join dept d on e.deptno=d.deptno;
Spark-sql:
4、spark-sql(有空可以研究下)
./spark-sql --master local[2] --jars /opt/lib/mysql-connector-java-5.1.47.jar --driver-class-path
标红这里就成了SparkSQL作业了。
注意:
./spark-sql --master local[2] --jars /opt/lib/mysql-connector-java-5.1.47.jar 不加--driver-class-path
会报错“没有合适的driver文件”但是确实我们已经指向了mysql驱动,这里需要再加参数--driver-class-path(
注释说可以自动加载jar包和驱动,实际不可以)
./spark-sql --master local[2] --jars /opt/lib/mysql-connector-java-5.1.47.jar --driver-class-path /opt/lib/mysql-connector-java-5.1.47.jar
才可以成功启动spark-sql!!!
所以有时候加载顺序,以及官网解释也不一定准,要自己测。
5、Spark数据缓存
case住table emp
cache table emp;
Spark后台:
原本cache是lazy的操作,不应该有action行为,但现在通过spark-sql,cache已经有eager的特性。所以能够马上后台显示。
总结:
Hive可以通过Spark-shell和Spark-sql访问。
四、explain
1、执行计划
创建表
create table ruoze_test(key string,value string);
explain:
explain select a.key*(5+6), b.value
from ruoze_test a join ruoze_test b
on a.key=b.key and a.key>10;
根据下图:
拆分指的是将未解决的逻辑计划通过schema再构建逻辑计划。
Physical Plan已经是最终的结果了,如果要看更详细的,需要加extend
explain extended select a.key*(5+6), b.value
from ruoze_test a join ruoze_test b
on a.key=b.key and a.key>10;
本来应该人工优化的地方,Spark自动优化了。
引申:
大数据处理最简单的方式就是忽略它。就是无关紧要的数据,先去掉,再处理。
五、spark-thriftserver
1、跟Hive里面的hiveserver2对应
2、start-thriftserver.sh
跟其他Spark程序启动一样:
./start-thriftserver.sh --master local[2] --jars /opt/lib/mysql-connector-java-5.1.47.jar
tail -200f /opt/app/spark-2.3.2/spark-2.3.2-bin-2.6.0-cdh5.7.0/logs/spark-HBinz-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-hadoop002.out
UI:
3、连接thriftserver服务来访问Spark-sql
(1)beeline
beeline -u jdbc:hive2://192.168.137.131:10000/default -n HBinz
Spark-sql成功连接。
六、代码连接Spark-sql
1、通过JDBC连接Spark ThriftServer
package com.HBinz.spark.Spark.sql.day01
import java.sql.DriverManager
/*
通过JDBC连接Spark ThriftServer
*/
object SparkSQLClientApp {
def main(args: Array[String]): Unit = {
Class.forName("org.apache.hive.jdbc.HiveDriver")
val connect = DriverManager.getConnection("jdbc:hive2://192.168.137.131:10000","HBinz","")
val stmt = connect.prepareStatement("select empno,ename,deptno from emp limit 10")
val rs = stmt.executeQuery()
while (rs.next()){
println("empno:" + rs.getInt("empno") + "ename:" + rs.getString("ename"))
}
rs.close()
stmt.close()
connect.close()
}
}
报错:
根据提示需要添加hive-jdbc的依赖。
(1)hive-jdbc
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>${hive.version}</version>
</dependency>
总结:
Thriftserver和Spark-shell以及Spark-sql的区别:
1、Thriftserver长服务,节省很多启动的资源消耗
2、将作业提交到客户端,客户端一个HTTP请求到服务就可以了,不需要重新申请资源
问题:
代码如何启动ThriftServer?HUE就是这么实现的。