Catalyst Optimizer
- 在投影上找到过滤器
- 检查筛选器是否可以在投影之前进行计算
- 如果是,则切换操作
select name from(
select id,name from people
) p
where p.id=1
Spark SQL API
- SparkContext
Driver与Spark Cluster (Workers)的对接
Spark功能的主要入口点 - SQLContext
在Spark中封装所有的关系功能 - SparkSession
提供与底层Spark功能交互的单一入口点,并允许用DataFrame和Dataset apl编程Spark。 - DataFrame - SchemaRDD
- DataSet - Generic DataFrame
- HiveContext
SQLContext的超集
面试题:dataFrame 和 Rdd的区别
- rdd装进来没有格式信息
dataFrame装进去有格式信息 - rdd可以装一些非结构化的数据
dataFrame装的是结构化的数据
DataFrame(DF) RDD
- 在阅读模式
- 可处理结构化和半结构化数据
- 简化了对结构化数据的处理
- 跟踪模式信息
- 读/写结构数据,如JSON, Hive表,Parquet等。
- Spark应用程序中的SQL
- 最佳性能和更强大的操作API
- 通过SQLContext / SparkSession访问
- lntegrated with ML
Seq List RDD 建表
import org.apache.spark.SparkContext
import org.apache.spark.sql.{Dataset, SparkSession}
object CreateDaTaset {
def main(args: Array[String]): Unit = {
//创建一个sparkSession
val spark:SparkSession=SparkSession.builder()
.master("local[4]")
.appName(this.getClass.getName)
.getOrCreate()
//创建一个SparkContext
val sc:SparkContext= spark.sparkContext
//创建一个隐式转换
import spark.implicits._
//通过Seq创建DataSet
val SeqDs:Dataset[Int]=spark.createDataset(1 to 3)
SeqDs.show()
//通过List集合
val listDs:Dataset[(String,Int)]=spark.createDataset(List(("a",1),("b",2)))
listDs.show()
val rddDs:Dataset[(String,Int,Int)]=spark.createDataset(
sc.parallelize(List(("a",1,2),("b",2,2),("c",3,3))))
rddDs.show()
}
}
+-----+ +---+---+ +---+---+---+
|value| | _1| _2| | _1| _2| _3|
+-----+ +---+---+ +---+---+---+
| 1| | a| 1| | a| 1| 2|
| 2| | b| 2| | c| 3| 3|
| 3| +---+---+ +---+---+---+
+-----+
join
import org.apache.spark.SparkContext
import org.apache.spark.sql.{Dataset, SparkSession}
object CreateGory {
//创建两个样例类
case class Point(label:String,x:Double,y:Double)
case class Category(id: Long, name: String)
def main(args: Array[String]): Unit = {
val spark:SparkSession=SparkSession.builder()
.master("local[4]")
.appName(this.getClass.getName)
.getOrCreate()
//创建一个SparkContext
val sc:SparkContext= spark.sparkContext
import spark.implicits._
val points:Dataset[Point]=Seq(Point("bar",2.1,2.5),Point("foo",3.2,3.5)).toDS()
val categories:Dataset[Category]=Seq(Category(1,"bar"),Category(2,"foo")).toDS()
points.join(categories,points("label")=== categories("name")).show()
}
}
+-----+---+---+---+----+
|label|x |y |id |name|
+-----+---+---+---+----+
|bar |2.1|2.5|1 |bar |
|foo |3.2|3.5|2 |foo |
+-----+---+---+---+----+
创建DataFrame
文件内容
{"name":"Michael"}
{"name":"Andy","age":30}
{"name":"Justin","age":19}
import org.apache.spark.sql.SparkSession
object DataFrameJson {
def main(args: Array[String]): Unit = {
val spark:SparkSession=SparkSession.builder()
.master("local[4]")
.appName(this.getClass.getName)
.getOrCreate()
val df=spark.read.json(
"file:///D:\\java\\IDE\\IntelliJ IDEA 2018.2.8\\Scalas\\.idea\\file\\person")
df.show()
}
}
+----+-------+
| age| name|
+----+-------+
|null|Michael|
| 30| Andy|
| 19| Justin|
+----+-------+
DataFrame API常规操作
import org.apache.spark.sql.{DataFrame, SparkSession}
object DataFrame {
def main(args: Array[String]): Unit = {
val spark:SparkSession=SparkSession.builder()
.master("local[4]")
.appName(this.getClass.getName)
.getOrCreate()
//加载json格式数据
val df:DataFrame=spark.read.json("file:///")
//打印dataframe的Scheme信息
df.printSchema()
//select 方法显示我们想要的字段
df.select("name").show()
//select 方法对我们想要的字段+1
df.select(df("age")+1)
//filter 过滤出符合条件的列
df.filter(df("age")>21).show()
//分组计数
df.groupBy("age").count().show()
//创建一张临时表 并使用SQL语句进行查询
df.createGlobalTempView("people")
spark.sql("select * from people").show()
}
}
map,
flatMap ,
sample 抽样,
filter 过滤
sort 排序
pipe 管道
groupBy 分组
groupByKey reduceByKey 对key进行分组
cogroup 对两个rdd进行key相同合并value 每个rdd的value在一个小集合里
reduce
fold
partitionBy 对rdd进行重分区
zip 拉链
unionjoin 并集
crossJoin 交集
leftOuterJoin 左外连接
rightOuterJoin 右外连接
count 计数
save 在对 rdd 使用 write 方法后保存到文件中
first rdd第一列
take rdd取数据
agg(max,min,sum,avg)
withColumn 对DateFrame的列进行操作
加载数据
除去csv文件的抬头
val lines = sc.textFile("file:///home/kgc/data/users.csv"")
//方式一 分区截取 分区号为0 并删除 idx分区号 iter 分区内容
val fields = lines.mapPartitionsWithIndex((idx, iter)=>
if idx == 0 iter.drop(1) else iter).map(l=>l.split(","))
//匹配首行开头的内容 为false
val fields =lines.filter(l=>l.startsWith("user_id")==false).map(l=>l.split(" ,"))
//把抬头作为字段名
scala> val df = spark.read.format ("csv" ).option ("header","true").option (
"delimiter","," ).load("hdfs:1llevents/data/events.csv")
format() 数据格式
option() 是否有抬头
option() 字段分割符
load() 数据位置
显示完整信息
val df1 = df.select("user_id","event_id","start_time","city","state")
df.printSchema
df1.show(5,false) //显示五条 不隐藏字段的内容
别名
//导包 二选一
import org.apache.spark.sql.functions._
import org.apache.spark.sql.functions.col
//查找data的字段并起别名
val datal = data.select(col("_c0" ).as ("interested" ),
col("_c1").as("user_id"),col("_c2").as( event_id" ))
//打印模式
data1.printSchema
//显示
data1.show
RDD 转换为 DataFrame
zhangsan,25
lisi,24
wangwu,27
zhaoliu,28
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{IntegerType, StringType, StructType,StructField}
import org.apache.spark.sql.{DataFrame, Row, SparkSession}
object DataFrame2 {
case class People(name: String, age: Int)
def main(args: Array[String]): Unit = {
val spark:SparkSession=SparkSession.builder()
.master("local[4]")
.appName(this.getClass.getName)
.getOrCreate()
//创建一个SparkContext
val sc:SparkContext= spark.sparkContext
import spark.implicits._
//加载数据
val peopleRDD:RDD[String]=sc.textFile("file:///D:\\java\\IDE\\IntelliJ IDEA 2018.2.8\\Scalas\\.idea\\file\\people")
//DataFrame是Dataset[Row]的泛型 DataFrame提供了更多的api
val peopleDF:DataFrame=peopleRDD
.map(_.split(","))
.map(x=>People(x(0),x(1).toInt))
.toDF()
peopleDF.show()
//创建临时表
peopleDF.createOrReplaceTempView("people1")
//执行sql语句
spark.sql("select * from people1 where name='zhangsan'").show()
val schema = StructType(Array(
StructField("name",StringType,true),
StructField("age",IntegerType,true)
))
val peopleRowRDD:RDD[Row]=peopleRDD
.map(_.split(","))
.map(x=>Row(x(0),x(1).toInt))
val df:DataFrame=spark.createDataFrame(peopleRowRDD,schema)
df.createOrReplaceTempView("people2")
spark.sql("select * from people2 ").show()
spark.read.format("")
}
}
+--------+---+
|zhangsan| 25|
| lisi| 24|
| wangwu| 27|
| zhaoliu| 28|
+--------+---+
+--------+---+
| name|age|
+--------+---+
|zhangsan| 25|
+--------+---+
+--------+---+
| name|age|
+--------+---+
|zhangsan| 25|
| lisi| 24|
| wangwu| 27|
| zhaoliu| 28|
+--------+---+
示例
表名("列名")
$("列名")
col(“列名”)
toncat(符号,字段1,字段2)