1)Spark SQL是Spark的一个组件,能够很好的处理结构化数据
2)Spark SQL记录了更多数据结构化信息, 所以相比RDD,可以更好的处理结构化数据,并且具有更好的性能
3)SparkSQL性能高的原因举例说明:一般的数据库读表中某个字段的数据,先拿到字段内容,然后还要去 元数据表获得这个字段表示什么含义,来来回回的查,效率低,Spark SQL就不需要这样,他一拿到字段内容就知道是什么意思,因为他记录了字段的含 义,不需要去查元数据表来感知这个字段什么含义,效率就提升了
4)首先应该了解RDD缺陷:
5) 通过SQL查询返回的结果是Dataset/DataFrame
DataFrame是一个分布式的数据集合,该数据集合以命名列的方式进行整合
Dataframe=RDD【数据集合】+Schema【模型】,实质可以理解为关系型数据库中的一个表(Table)
DataFrame在1.3.0版本之前,称为SchemaRDD,是存放Row对象的RDD,每个Row对象代表一行记录
1.将sparkSQL的依赖添加至pom.xml文件【根据你安装的具体版本到maven仓库中寻找依赖】
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.1.2</version>
</dependency>
2.创建SparkSession
val session = SparkSession.builder().master("local[2]").appName("DF").getOrCreate()
3.加载List集合对象(内部数据源),生成DF
val persion = List(("zhangsan",15),("lisi",18),("wangwu",20)) //创建一个List集合对象
val persion_df =session.createDataFrame(persion) //加载List对象再生成DataFrame
4.对生成的DF对象进行操作
persion_df.show() //返回所有行数据
+--------+---+
| _1| _2|
+--------+---+
|zhangsan| 15|
| lisi| 18|
| wangwu| 20|
+--------+---+
persion_df.select("_1").show() //返回第一个字段的所有数据
+--------+
| _1|
+--------+
|zhangsan|
| lisi|
| wangwu|
+--------+
persion_df.select().where("_2 > 17").show() //返回第二个字段大于17数据
+------+
| _1|
+------+
| lisi|
|wangwu|
+------+
通过createDataFrame()加载内部数据构建DF
object sparkSQL {
case class Person(name:String,age:Int,address:String) //样例类,列的字段
def main(args: Array[String]): Unit = {
//创建一个会话,SparkSession对象
val session =SparkSession.builder().master("local").appName("DF").getOrCreate()
//将List集合对象转化为 DF
val person = List(("zhangsan",15),("lisi",18),("wangwu",20))
val person_df =session.createDataFrame(person)
person_df.show()
//将rdd数据集转换为 DF
val rdd = session.sparkContext.textFile("file:///f:\\dataTest\\users.txt")
val rdd1 = rdd.map(x=>x.split(" ")).map(x=>(x(0),x(1),x(2))) //将 rdd 转换成tuple元组类型
val rdd2 = rdd.map(x=>x.split(" ")).map(x=>new Person(x(0),x(1).toInt,x(2))) //转换为样例类
val person_df_rdd1 = session.createDataFrame(rdd1) //创建 DF
val person_df_rdd2 = session.createDataFrame(rdd2) //创建 DF
person_df_rdd1.show()
person_df_rdd2.show()
}
}
// 样例类包装后输出结果:
+------+---+-------+
| name|age|address|
+------+---+-------+
| anne| 22| NY|
| joe| 39| CO|
|alison| 35| NY|
| mike| 69| VA|
| marie| 27| OR|
+------+---+-------+
通过SparkSession 的 read加载外部数据源
说明:通过session.read加载外部不同数据源,包括:json、orc、parquet、csv、file等等。
// 举例说明:
val session =SparkSession.builder().master("local").appName("DF").getOrCreate()
val sess_df = session.read.text("file:///f:\\dataTest\\users.txt")
sess_df.show()
// 输出结果:
+------------+
| value|
+------------+
| anne 22 NY|
| joe 39 CO|
|alison 35 NY|
| mike 69 VA|
| marie 27 OR|
+------------+
通过隐式类型转换,直接将Scala中的集合转为DF
val session1 = SparkSession.builder().master("local[2]").appName("DF").getOrCreate()
val person = List(("zhangsan",12),("lisi",23),("wangwu",34))
import session1.implicits._ //先手动引入spark中隐式转换的包
val person_df = person.toDF() //调用toDF()方法实现转换
person_df.show()
//输出结果:
+--------+---+
| _1| _2|
+--------+---+
|zhangsan| 12|
| lisi| 23|
| wangwu| 34|
+--------+---+
DF.printSchema() 打印当前DF的模型
例如上述举出的例子:
person_df_rdd1.printSchema()
person_df_rdd2.printSchema()
//输出
root
|-- _1: string (nullable = true)
|-- _2: string (nullable = true)
|-- _3: string (nullable = true)
root
|-- name: string (nullable = true)
|-- age: integer (nullable = true)
|-- address: string (nullable = true)
注意: 加载外部数据源时,对Json文件支持比较好,可以进行模型推断(字段列出)。但转换出来后底层都是Sring类型
val dftest =session.read.json("file:///f:\\dataTest\\test.json")
dftest.show(5)
dftest.printSchema()