一、上次课回顾
第一章:Spark SQL的认识
第二章:DataSet和DataFrame
第三章:Spark SQL运行
回顾:SparkCore总结,把数据写到外部第三方数据库,都要采用foreachPartition
建议大家首先采用带Partition的。
对于Spark-Core给定功能实现,是最基本的要求;数据清洗部分使用RDD代替MapReduce来实现.
Spark SQL仅仅是写sql,在spark2.4.3中,叫SQL,DataFrame,DataSet
Spark SQL就是Hive on Spark 这个观点是错误的。
1、SparkSQL 是1.0版本出来的,于1.3版本毕业
2、从Spark SQL框架来说:
在Spark分支中有了Spark SQL;
在Hive中也有了一个分支,Hive on Spark.只是spark SQL的语法借鉴的Hive on Spark多一点。
只需要一个命令:set hive.execution.engine = spark
hive on spark:生产慎用,很多功能还不是很完善
翻译:它可以无缝的将SQL查询和Spark程序对接起来。
Spark SQL允许你使用SQL或者DataFrame API 来查询结构化数据在Spark程序中
举例如下:
spark.read.json("s3n://...")
.registerTempTable("json")
results = spark.sql(
"select * from people JOIN json ......"
)
Run SQL or HiveQL queries on existing warehouse.
运行SQL或者HiveQL在已经存在的数据库
Spark SQL supports the HiveQL syntax as well as Hive SerDes and UDFs,allowing you to access existing Hive warehouses.
Spark SQL支持HiveQL的语法和Hive序列化和UDF函数,同样允许你去访问已有的Hive数据仓库
思考:新框架不能访问已有的数据仓库,我们会去使用它么;支持已有的数据仓库,我们就可以尝试迁移部分
JDBC去查的是Spark中的什么数据?通常情况下去查结果数据,总不可能使用JDBC让它去跑一个大查询数据吧d
熟读官网:
1、Spark SQL is a Spark module for structured data processing.unlike the basic Spark RDD,
译:Spark SQL是一个spark的模块用于处理结构化数据,它不同于基础的spark RDD
2、the interfaces provided by Spark SQL provide Spark with more information about the structure of both the data and the computation being performed
译:由Spark SQL提供的接口能够提供的信息不仅仅是数据层面,还包括计算层面。
3、Internally,Spark SQL uses this extra information to peform extra optimizations. There are several ways to interact with Spark SQL including SQL and the Dataset API.
译:Spark SQL使用额外的信息做额外的优化,有很多方式可以进行API交互,
有SQL API和DataFrame API.
4、when computing a result the same execution engine is used , independent of which API/language you are using to express the computation. This unification means that developers can easily switch back and forth between different APIs based on which provides the most natural way to express a given transformation.
SQL:
one use of Spark SQL is to execute SQL queries. Spark SQL can also be used to read data from an existing Hive installation.
Spark SQL能够被用来读取数据在一个已经存在的Hive库中。
问题:如果我们的机器上面没有安装Hive,能否使用Spark SQL去读取Hive库?
回答:可以不安装,只要有hive-site.xml这个配置文件就行了,共用一套元数据信息。
误区:跑Spark on yarn,要去生产上拉个集群???
只要有hive-site.xml,他能连接到元数据信息即可。
DataFrames是借鉴与python中的pandas.
RDD很麻烦,比如x._2._1过了一天可能就不知道怎么写了。
同样一个功能,不同人有不同种写法,RDD调优起来麻烦。
蚂蚁金服视频面试还考察RDD,但是RDD中的算子也很重要。
RDD写起来痛苦,Map Reduce写起来也痛苦。
R/Pandas:单机,不适用于集群。
==>所以DataFrame框架应运而生。
DataFrame诞生版本:1.3,在这之前它的名字叫SchemaRDD.
A Dataset is a distributed collection of data.
A DataFrame is a Dataset organized into named columns.
DataFrame是一个分布式的数据集组织成带名字的列。
17er = name
==>理解为一个框 拆分
==>table
It is conceptually equivalent to a table in a relational database or a data frame in R/Python,
它等价于是关系型数据库的一张表或者是一个data frame 在python中,
but with richer optimizations under the hood.
==>通过这句话的richer要能够想到隐式转换。
Dataset is a new interface added in Spark 1.6 that provides the benefit of RDDs(Strong typing, ability to use powerful manbda functions) with the benefits of Spark SQL’s optimized execution engine. A Dataset can be constructed from JVM objects and then manipulated using functional transformations(map,flatMap,filter).
The Dataset API is available in Scala and Java. Python does not have the support for the Dataset API.
注意:
in the scala API,DataFrame is simply a type alias of Dataset[Row]
alias指的是别名:
DataFrame = Dataset[Row]
三者都是一个集合,可以分布式执行;
比如一张表student,有三个字段:id name age,在RDD中,它只知道装了一个student表,而DataFrame能够知道表中信息。
DataFrame = table
id name age
1 aa 15
2 bb 16
3 cc 17
同样的功能使用类似的代码,使用Java scala python语言他们的开发执行性能?
差别很大,但是有了DataFrame之后就不一样了。
不管什么语言,java scala python经过DataFrame之后,都会变成Logical Plan(逻辑执行计划)
1、先启动spark,./spark-shell
Spark session available as ‘spark’
Spark Session:整个程序的入口。
2、直接运行,spark.sql(“show tables”).show
结果:数据库没有,表没有,临时表没有。
那怎么办呢?
把hive里conf目录下的hive-site.xml拷贝到spark下的conf目录,确保在SPARK_HOME/conf下有hive-site.xml
直接报错,报错信息提取如下,主要关注caused by:
提炼报错信息:在CLASSPATH中找不到com.mysql.jdbc.Driver这个驱动包。
Caused by: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
Caused by: java.lang.reflect.InvocationTargetException
Caused by: javax.jdo.JDOFatalInternalException: Error creating transactional connection factory
NestedThrowables
Caused by: org.datanucleus.exceptions.NucleusException: Attempt to invoke the "BONECP" plugin to create a ConnectionPool gave an error : The specified datastore driver ("com.mysql.jdbc.Driver") was not found in the CLASSPATH. Please check your CLASSPATH specification, and the name of the driver.
Caused by: org.datanucleus.exceptions.NucleusException: Attempt to invoke the "BONECP" plugin to create a ConnectionPool gave an error : The specified datastore driver ("com.mysql.jdbc.Driver") was not found in the CLASSPATH. Please check your CLASSPATH specification, and the name of the driver.
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
Caused by: java.lang.reflect.InvocationTargetException: javax.jdo.JDOFatalInternalException: Error creating transactional connection factory
3、处理方案:添加驱动包
问题点:缺少com.mysql.jdbc.driver驱动包,查看命令帮助进行jar包提交。
–jars JARS Comma-separated list of jars to include on the driver //这个命令肯定可以提交到executor端,不一定能提交到driver端。
–driver-class-path Extra class path entries to pass to the driver. //使用这个命令
我们使用命令:spark-shell --jars /usr/share/java/mysql-connector-java-5.1.46-bin.jar,在相对应的WebUI上可以查看到提交的jar包。
ps -ef|grep 3192
[java] 这是一个僵尸进程
僵尸进程在哪里能看到:top查看负载的时候能看到
打开hadoop004:4040,点击environment,我们拉到最后,有一行提示,added by user,然后跟上jar包名,说明我们已经把这个jar包提交上去了。
我们在webUI界面上看到了ClassPath,那些jar包又是在什么地方的呢,cd $SPARK_HOME/jars,下面一堆jar包,这些jar包会在WebUI上体现。
对于提交jar包,不适合用cp直接拷贝到SPARK_HOME/jars下使用,这样的话会影响到别人使用spark。
我们除了指定–jars还需要指定–driver-class-path:
./spark-sql --jars /home/hadoop/lib/mysql-connector-java-5.1.46-bin.jar --driver-class-path /home/hadoop/lib/mysql-connector-java-5.1.46-bin.jar
第一步:提交jar包后顺利进入spark-shell启动页,spark-2.4.2-bin-2.6.0-cdh5.7.0]$ spark-shell --jars /usr/share/java/mysqctor-java-5.1.46-bin.jar
第二步:查看有几个数据库
第三步:使用ruoze_d6这个数据库,并查看ruoze_d6这个数据库中表信息
第四步:打印出emp表中的所有信息
顺利进入:show tables;
https://blog.csdn.net/zhikanjiani/article/details/89075266
再次启动spark-shell,spark.sql(“select * from emp”).show(false)
数据全出来了。
更简便的方式,cd $SPARK_HOME/bin目录下,有一个spark sql,
使用如下命令:./spark-sql --jars ~/software/mysql-connector-java-5.1.27-bin.jar
报错:No Suitable driver found.
此时就是要指定Driver-ClassPath
评论:用了Spark SQL后就没有Hive什么事了。
Spark SQL底层调用的是Spark-submit
Spark shell底层调用的也是Spark-submit
数仓可以使用Hbase和Hive,实时数仓不一定使用Hbase.
jps把SparkSubmit进程杀了,不然进程启太多了夯不住机器。
jps查看得到pid,ps -ef|grep pid 要把他的父进程杀掉才真的可以。
在spark sbin目录下有一个hs2,启动:./start-thriftserver.sh --jars ~/software/mysql-connector-java5.1.27-bin.jar
扩展:但是每次写这么个命令有点烦,进入到conf目录下,配置到spark-default,怎么配呢???
tail -200f 监听日志,
hs2作为服务端启动之后,要配置一个客户端来使用,进入到spark的bin目录下,执行如下命令:./beeline -u jdbc:hive2://localhost:10000 -n hadoop
成功进入客户端后,
也可以在webUI上查询,只有thriftserver使用的时候有的,有一个界面叫JDBC/ODBC Server
页面内容自行验证。web UI也是它的一个监控界面
首先需要在pom.xml中引入spark-sql的依赖:
idea下载不下来的话手动添加依赖包进去。
package sparksql01
import org.apache.spark.sql.SparkSession
object SparkSessionApp {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
.master("local[2]") //
.appName("SparkSessionApp") //
.getOrCreate() //
spark.read.json("C:\\Users\\Administrator\\Desktop\\people.json")
spark.sql("name").show
spark.stop()
}
}
我们点进spark.sql("").show 点进sql这个源码里面去;它的定义如下:
/**
* Executes a SQL query using Spark, returning the result as a `DataFrame`.
* The dialect that is used for SQL parsing can be configured with 'spark.sql.dialect'.
*
* @since 2.0.0
*/
def sql(sqlText: String): DataFrame = {
Dataset.ofRows(self, sessionState.sqlParser.parsePlan(sqlText))
}
这是一个sql解析,sqlParse返回的就是一个逻辑执行计划
在spark-shell客户端下默认展示的是前20条信息
使用:spark.sql(“select * from emp”).show()
字符串长度超过20,还会把超过20的字符给戒掉
/**
* Displays the top 20 rows of Dataset in a tabular form. Strings more than 20 characters
* will be truncated, and all cells will be aligned right.
*
* @group action
* @since 1.6.0
*/
def show(): Unit = show(20)
StringBuilder大SB,String Buffer小sb.