maven依赖
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.4.5</version> </dependency>
1、常规准备
1)写代码创建环境
2)导入隐式转换
3)需要使用到 sql的需要先创建视图
4)读取csv格式的文件需要指定列头
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, Dataset, SparkSession}
object SparkSqlTest1 {
def main(args: Array[String]): Unit = {
/**
* 可以通过sparkconf来创建sparksession对象,也可以直接创建
* val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("SparkSQL")
*
* val sparkSession = SparkSession.builder().config(sparkConf).getOrCreate()
*/
val spark: SparkSession = SparkSession .builder()
//这个mater是在本地测试的时候要加上的,在集群上运行需要删除,
.master("local[*]")
.appName("SparkSqlTest1")
.getOrCreate()
//读取csv格式的数据我们需要自己添加表头
val stuDF: DataFrame = spark
.read
.schema("id Int,name String,age Int,gender String,clazz String")
.csv("data/students.txt")
//添加视图,可以在sql中使用
stuDF.createOrReplaceTempView("stu_view")
spark.sql("select * from stu_view").show()
spark.sql("select name,age from stu_view").show()
spark.sql("select avg(age) from stu_view").show()
stuDF.select("age","name").show()
/**
* 下面这里涉及到了转换操作,需要导入隐式转换
* 使用隐式转换
*/
import spark.implicits._
stuDF.select($"age+1",$"name").show()
stuDF.show()
spark.close()
}
}
2、RDD DataFrame DataSet三者转换
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}
object TransformTest {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.master("local[*]")
.appName("TransformTest")
.getOrCreate()
import spark.implicits._
/**
* RDD -> DataFrame
* 相比RDD,DataFrame多了结构
*/
val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(List((1, "zhangsan", 30), (2, "lisi", 40)))
val df: DataFrame = rdd.toDF("id", "name", "age")
val rowRDD: RDD[Row] = df.rdd
/**
* RDD <=> DataSet
*/
val newDS: Dataset[User] = df.as[User]
val newDF: DataFrame = newDS.toDF()
val DS2: Dataset[User] = rdd.map {
case (id, name, age) => {
User(id, name, age)
}
}.toDS()
val rdd2 = DS2.rdd
//关闭连接
spark.close()
}
}
case class User(id:Int,name:String,age:Int)
3、UDF函数
import org.apache.spark.sql.{DataFrame, SparkSession}
object UDFTest {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.master("local[*]")
.appName("TransformTest")
.getOrCreate()
import spark.implicits._
val stuDF: DataFrame = spark
.read
.schema("id Int,name String,age Int,gender String,clazz String")
.csv("data/students.txt")
val stu = stuDF.createOrReplaceTempView("stu")
/**
* 注册udf函数,传入函数名,函数方法,一进一出
*/
spark.udf.register("prefixName",(name:String)=>{
"$name$: "+name
})
spark.sql("select prefixName(name) from stu").show()
spark.close()
}
}
UDAF
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types.{DataType, LongType, StructField, StructType}
import org.apache.spark.sql.{DataFrame, Row, SparkSession}
object UDAFTest {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.master("local[*]")
.appName("UDAFTest")
.getOrCreate()
val stuDF: DataFrame = spark
.read
.schema("id Int,name String,age Int,gender String,clazz String")
.csv("data/students.txt")
val stu = stuDF.createOrReplaceTempView("stu")
/**
* 自定义UDAF函数需要继承UserDefinedAggregateFunction类
*/
spark.udf.register("avg_age",new myAvgUDAF())
spark.sql("select avg_age(age) from stu").show()
spark.close()
}
/**
* 自定义聚合函数类,计算平均年龄
*/
class myAvgUDAF extends UserDefinedAggregateFunction{
//输入结构
override def inputSchema: StructType = {
StructType(
Array(
StructField( "age",LongType))
)
}
//缓冲区数据的结构
override def bufferSchema: StructType = {
StructType(
Array(
StructField( "age",LongType),
StructField( "count",LongType)
)
)
}
//函数计算的结果
override def dataType: DataType = LongType
//函数的稳定性
override def deterministic: Boolean = true
//初始化缓冲区的配置
override def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer.update(0,0L)
buffer.update(1,0L)
}
//来一条数据就更新缓冲区
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
//缓冲区第一个是传入数据的值,第二个是count计数
buffer.update(0,buffer.getLong(0)+input.getLong(0))
buffer.update(1,buffer.getLong(1)+1)
}
//缓冲区数据合并
override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer1.update(0,buffer1.getLong(0)+buffer2.getLong(0))
buffer1.update(1,buffer1.getLong(1)+buffer2.getLong(1))
}
//定义输出结果的计算模式
override def evaluate(buffer: Row): Any = {
buffer.getLong(0)/buffer.getLong(1)
}
}
}
4、读取数据和写数据
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}
object Demo2SourceAPI {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.appName("Demo2SourceAPI")
.master("local")
.getOrCreate()
spark.read
.schema("id Int,name String,age Int,gender String,clazz String")
//我们可以通过这个方法设置分割符号,有的文件如果不是逗号分割就使用这个方法
.option("sep","|")
.csv("spark/data.txt/student.txt")
/**
* 我们还可以指定某种格式读取数据
* 这里就读取一下json格式的数据
* 但是json里面一条数据就记录了一次列名,非常浪费空间
*/
val stuDF: DataFrame = spark
.read
.format("json")
.load("spark/data.txt/students.json")
stuDF.show(100)
/**
* 生成parquet文件
*/
stuDF
.write
.mode(SaveMode.Overwrite)
//指定输出格式指定写入的模式:
// Append追加、Overwrite覆盖、ErrorIfExists存在就报错、Ignore存在即忽略
.format("parquet")
//指定输出路径
.save("spark/data/parquet")
/**
* 写一个orc格式的文件
* orc格式是一个列式存储,有压缩的
* 从文件名我们可以看出来,这是通过snappy压缩的
*/
stuDF
.write
.mode(SaveMode.Overwrite)
//指定输出格式指定写入的模式:
// Append追加、Overwrite覆盖、ErrorIfExists存在就报错、Ignore存在即忽略
.format("orc")
//指定输出路径
.save("spark/data/orc")
/**
* 读取parquet文件,自带snappy,对数据进行压缩
*/
val parDF: DataFrame = spark
.read
.format("parquet")
.load("spark/data/parquet")
parDF.show(100)
/**
* 读取orc文件
*/
val orcDF: DataFrame = spark
.read
.format("orc")
.load("spark/data/orc")
orcDF.show(10)
/**
* 读取mysql的数据
*/
val jdbcDF: DataFrame = spark.read
.format("jdbc")
.option("url", "jdbc:mysql://doker:3306/student")
.option("driver","com.mysql.jdbc.Driver")
.option("dbtable", "student")
.option("user", "root")
.option("password", "123456")
.load()
jdbcDF.show()
stuDF.write
.format("jdbc")
.option("url", "jdbc:mysql://doker:3306/student")
.option("driver","com.mysql.jdbc.Driver")
.option("dbtable", "student1")
.option("user", "root")
.option("password", "123456")
.mode(SaveMode.Append)
.save()
spark.close()
}
}