sparkSQL
spark中处理结构化数据的组件
计算过程是DataSet和DataFrame之间的转换
SparkSql可以与SparkCore相互转换,
通过SparkSession类里面有一个SparkContext属性
DS/DF可以创建出来,也可以由其他DS/DF转换而来
DS:数据的集合
DF:在DS基础上条件了 schema(表头)
使用
1.创建一个SparkSession
val spark:SparkSession = SparkSession.builder()
.master()
.appName()
.getOrCreate()
import spark.implicits._ (必须写在sparkSession里,是内部Object)
2.读写数据
读:
//没有格式化,默认使用parquet类型读取数据
a.spark.read.format(type).load(path)
//简化形式
b.spark.read.type(path)
写:
//没有格式化,默认写入parquet类型数据
a.df.write.format(type).save(path)
//简化形式
b.df.write.type(path)
printSchema()读取结果数据的结构
3.分析数据
a.SQL
所有的操作全都交给sql语句
这里的sql语法不完全与任何sql语法一致
通过 spark.sql(sql语句) 执行
四种创建临时表/视图的方式,创建是存在sparkSession中
(创建临时视图)
1)createTempView(就只是创建,重名报错)
2)createOrReplaceTempView(如果有重名的表名则替换,无就创建)
(创建全局临时视图)
3)createGlobalTempView(就只是创建,重名报错)
4)createOrReplaceGlobalTempView(如果有重名的表名则替换,无就创建)(查询表名的时候要加上global_temp)
r.createTempView("peo")
r.createOrReplaceTempView("peo")
r.createOrReplaceGlobalTempView("people")
val Sqlres=spark.newSession()sql("select * from global_temp.people")
Sqlres.show()
Sqlres.printSchema()
创建持久化表
相当于写文件与创建表的整合
.saveAsTables()
路径要在配置文件中修改,可以使用option(key,value)方法
dataDF.write.option("path","E://path").saveAsTable("peo")
val resDF = spark.sql("select * from peo")
resDF.show()
b.DataSet API
DataSet可以通过调用函数的形式对数据进行分析
只要是sql语句可以支持的操作都有相对应的API与之对应
可以使用$获取相应字段内容,且进行运算,前提必须先引入隐式,且一个加了全部变量都得加
DF.select()
DF.where()
DF.filter()
DF.group().count()
…
4.几种转换关系
1.普通集合转DS/DF
语法:
集合.toDS()
集合.toDF()
集合.toDF(列名*)
注意:
a.使用这几个中的任意一个方法都必须引入隐式转换
b.toDS和toDF()没有任何区别
c.如果相加表头,使用toDF(列名),列名的个数与列的数量必须一致
d.如果想创建多列的数据,原始集合中的每个元素应该是元组类型
2.RDD转换成DS/DF
a.语法与普通集合转RDD一致
b.可以把RDD里的数据转成一个类的实例化对象的形式返回
sparkSQL可以通过类的参数反射推断出相应的列名
前提是要有可以实例化对象的类
import spark.implicits._
val sc = spark.sparkContext
val rdd = sc.textFile("E://data_resources/people.txt")
.map(line=>{
val nameAndAge = line.split(",")
val name = nameAndAge(0)
val age = nameAndAge(1)
//原始数据没有schema,可以把每行数据变成类的实例化对象的形式
//通过反射机制 类中的属性名直接可以充当数据的 schema
People(name,age.trim.toInt)
})
rdd.toDS().show()
3.RDD转换成DS/DF,人为设计schema
可以由开发人员自己控制每个字段的各种属性
三个步骤
a.把原始RDD转成Row类型的RDD
b.根据原始数据的字段封装schema
c.val DF = sc.createDataFrame(RDD,schema)
4.DS/DF 转成 RDD
DS/DF.rdd
注意:DF转过来的RDD为Row类型的RDD,注意每个字段的类型
def createDFByDIY(spark:SparkSession)={
// a.把原始RDD转成Row类型的RDD
val sc=spark.sparkContext
val rdd=sc.textFile("D://work/wordCount.txt")
.map(line=>{
val nameAndAge=line.split(" ")
Row(nameAndAge(0),nameAndAge(1))
})
// b.根据原始数据的字段封装schema
val schema_str="name age"
val fields=schema_str.split(" ")
.map(fieldname=>{
if (fieldname.equals("name")){
StructField(fieldname,StringType,false)
}else {
StructField(fieldname, StringType, false)
}
})
// c.val DF = sc.createDataFrame(RDD,schema)
val schema=StructType(fields)
val resDF=spark.createDataFrame(rdd,schema)
resDF.show()
}
5.SQL语句直接读取文件
通过sql语句直接读取文件内容,获取相应的DF
语法:
spark.sql(“select * from type.path
”)
6.保存模式
a.ErrorIfExists:默认存储模式,如果存在就直接抛异常
b.Append:追加内容,向同一个目录追加文件
在原目录中创建一个新的文件而不是追加到原有的文件
但不影响读取数据,当读取的是目录时,都是以一个文件的形式进行读取
c.Overwrite:覆盖,把原内容删除,添加新内容
d.Ignore:忽略,如果内容存在不做任何修改,如果不存在,添加。
两种使用方式:
a. .mode(“Ignore”)
b. .mode(SaveMode.Ignore)