Hive,它是将Hive SQL转换成MapReduce,然后提交到集群上执行的,大大简化了编写MapReduce程序的复杂性,但MapReduce这种计算模型执行效率比较慢。
类比Hive,SparkSQL是Spark上的高级模块,SparkSQL是一个SQL解析引擎,将SQL解析成特殊的RDD(DataFrame),然后在Spark集群中运行Spark SQL,执行效率非常快!
SparkSQL是用来处理结构化数据的(先将非结构化的数据转换成结构化数据)
SparkSQL支持两种编程API:
在scala中,DataFrame其实就是Dateset[Row]
DataFrame里面存放的结构化数据的描述信息,DataFrame要有表头(表的描述信息),描述了有多少列,每一列数叫什么名字、什么类型、能不能为空?
DataFrame是特殊的RDD(RDD+Schema信息就变成了DataFrame)
在DataSet上的操作,也分为transformations和actions。transformations会产生新的DataSet,而actions则是触发计算并产生结果。transformations包括:map,filter,select和aggregate等操作。而actions包括:count,show或把数据写入到文件系统中。
SparkSQL 1.x和2.x的编程API有一些变化
package spark_SQL
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* Spark1.x 版本的 spark SQL
*/
object SQL1Demo1 {
def main(args: Array[String]): Unit = {
//提交的这个程序可以连接到Spark集群中
val conf = new SparkConf().setAppName("SQL1Demo1").setMaster("local[2]")
//创建SparkSQL的连接(程序执行的入口)
val sc = new SparkContext(conf)
//sparkContext不能创建特殊的RDD(DataFrame)
//将SparkContext包装进而增强
val sqlContext = new SQLContext(sc)
//创建特殊的RDD(DataFrame),就是有schema信息的RDD
//先有一个普通的RDD,然后在关联上schema,进而转成DataFrame
val lines = sc.textFile("hdfs://hadoop100:9000/person")
//将数据进行整理
val boyRDD: RDD[Boy] = lines.map(line => {
val fields = line.split(",")
val id = fields(0).toLong
val name = fields(1)
val age = fields(2).toInt
val fv = fields(3).toDouble
Boy(id, name, age, fv)
})
//该RDD装的是Boy类型的数据,有了shcma信息,但是还是一个RDD
//将RDD转换成DataFrame
//导入隐式转换
import sqlContext.implicits._
val bdf: DataFrame = boyRDD.toDF
//变成DF后就可以使用两种API进行编程了
//把DataFrame先注册临时表
bdf.registerTempTable("t_boy")
//书写SQL(SQL方法应其实是Transformation)
val result: DataFrame = sqlContext.sql("SELECT * FROM t_boy ORDER BY fv desc, age asc")
//查看结果(触发Action)
result.show()
sc.stop()
}
}
case class Boy(id: Long, name: String, age: Int, fv: Double)
package spark_SQL
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types._
import org.apache.spark.sql.{DataFrame, Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* Spark1.x 版本的 spark SQL
*/
object SQL1Demo2 {
def main(args: Array[String]): Unit = {
//提交的这个程序可以连接到Spark集群中
val conf = new SparkConf().setAppName("SQLDemo2").setMaster("local[2]")
//创建SparkSQL的连接(程序执行的入口)
val sc = new SparkContext(conf)
//sparkContext不能创建特殊的RDD(DataFrame)
//将SparkContext包装进而增强
val sqlContext = new SQLContext(sc)
//创建特殊的RDD(DataFrame),就是有schema信息的RDD
//先有一个普通的RDD,然后在关联上schema,进而转成DataFrame
val lines = sc.textFile("hdfs://node-4:9000/person")
//将数据进行整理
val rowRDD: RDD[Row] = lines.map(line => {
val fields = line.split(",")
val id = fields(0).toLong
val name = fields(1)
val age = fields(2).toInt
val fv = fields(3).toDouble
Row(id, name, age, fv)
})
//结果类型,其实就是表头,用于描述DataFrame
val sch: StructType = StructType(List(
StructField("id", LongType, true),
StructField("name", StringType, true),
StructField("age", IntegerType, true),
StructField("fv", DoubleType, true)
))
//将RowRDD关联schema
val bdf: DataFrame = sqlContext.createDataFrame(rowRDD, sch)
//变成DF后就可以使用两种API进行编程了
//把DataFrame先注册临时表
bdf.registerTempTable("t_boy")
//书写SQL(SQL方法应其实是Transformation)
val result: DataFrame = sqlContext.sql("SELECT * FROM t_boy ORDER BY fv desc, age asc")
//查看结果(触发Action)
result.show()
sc.stop()
}
}
package spark_SQL
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types._
import org.apache.spark.sql.{DataFrame, Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* Spark1.x 版本的 spark SQL
*/
object SQL1Demo3 {
def main(args: Array[String]): Unit = {
//提交的这个程序可以连接到Spark集群中
val conf = new SparkConf().setAppName("SQLDemo3").setMaster("local[2]")
//创建SparkSQL的连接(程序执行的入口)
val sc = new SparkContext(conf)
//sparkContext不能创建特殊的RDD(DataFrame)
//将SparkContext包装进而增强
val sqlContext = new SQLContext(sc)
//创建特殊的RDD(DataFrame),就是有schema信息的RDD
//先有一个普通的RDD,然后在关联上schema,进而转成DataFrame
val lines = sc.textFile("hdfs://node-4:9000/person")
//将数据进行整理
val rowRDD: RDD[Row] = lines.map(line => {
val fields = line.split(",")
val id = fields(0).toLong
val name = fields(1)
val age = fields(2).toInt
val fv = fields(3).toDouble
Row(id, name, age, fv)
})
//结果类型,其实就是表头,用于描述DataFrame
val sch: StructType = StructType(List(
StructField("id", LongType, true),
StructField("name", StringType, true),
StructField("age", IntegerType, true),
StructField("fv", DoubleType, true)
))
//将RowRDD关联schema
val bdf: DataFrame = sqlContext.createDataFrame(rowRDD, sch)
//不使用SQL的方式,就不用注册临时表了
val df1: DataFrame = bdf.select("name", "age", "fv")
import sqlContext.implicits._
val df2: DataFrame = df1.orderBy($"fv" desc, $"age" asc)
df2.show()
sc.stop()
}
}
创建SparkSession
package spark_SQL
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{DoubleType, IntegerType, LongType, StringType, StructField, StructType}
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}
object SQL2Demo1 {
def main(args: Array[String]): Unit = {
// spark2.x SQL的编程API(SparkSession) 是spark2.x SQL执行的入口
val spark = SparkSession.builder()
.appName("SQL2Demo1")
.master("local[*]")
.getOrCreate()
// 创建RDD
val lines: RDD[String] = spark.sparkContext.textFile("hdfs://hadoop100:9000/person")
// 数据整理
val rowRDD: RDD[Row] = lines.map(line => {
val fields = line.split(",")
val id = fields(0).toLong
val name = fields(1)
val age = fields(2).toInt
val fv = fields(3).toDouble
Row(id, name, age, fv)
})
// 创建表头,用于描述DataFrame
val schema: StructType = StructType(List(
StructField("id", LongType, true), // 名字,类型,是否可以为空
StructField("name", StringType, true),
StructField("age", IntegerType, true),
StructField("fv", DoubleType, true)
))
// 创建DataFrame
val df: DataFrame = spark.createDataFrame(rowRDD, schema)
// 以上数据整理、创建表头、创建DataFrame可以合成以下一步
// 需要导入隐式转换
//import spark.implicits._
// val rowDataFrame: DataFrame = lines.map(line => {
// val fields = line.split(",")
// val id = fields(0).toLong
// val name = fields(1)
// val age = fields(2).toInt
// val fv = fields(3).toDouble
// (id, name, age, fv)
// }).toDf("id","name","age","fv")
import spark.implicits._
val df2: Dataset[Row] = df.where($"fv" > 98).orderBy($"fv" desc, $"age" asc)
df2.show()
spark.stop()
}
}
支持多种数据源读写例如JDBC、CSV、JSON、parquet
package spark_SQL
import java.util.Properties
import org.apache.spark.sql.{DataFrame, SparkSession}
object DataSource {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("DataSource")
.master("local[*]")
.getOrCreate()
import spark.implicits._
/**
* 读
*/
/********** 读取csv格式数据 **********/
val csv: DataFrame = spark.read.csv("/Users/zx/Desktop/csv")
csv.printSchema()
val pdf: DataFrame = csv.toDF("id", "name", "age")
pdf.show()
/********** 读取jdbc数据 **********/
//load这个方法会读取真正mysql的数据吗? 不会,但会连接数据库读取schema信息
val logs: DataFrame = spark.read.format("jdbc").options(
Map("url" -> "jdbc:mysql://localhost:3306/bigdata",
"driver" -> "com.mysql.jdbc.Driver",
"dbtable" -> "logs",
"user" -> "root",
"password" -> "123568")
).load()
logs.printSchema()
//lambda表达式
val r = logs.filter($"age" <= 13)
//val r = logs.where($"age" <= 13)
val reslut: DataFrame = r.select($"id", $"name", $"age" * 10 as "age")
/********** 读取json数据 **********/
//指定以后读取json类型的数据(有表头)
val jsons: DataFrame = spark.read.json("/Users/zx/Desktop/json")
val filtered: DataFrame = jsons.where($"age" <=500)
filtered.printSchema()
/********** 读取parquet数据 **********/
val parquetLine: DataFrame = spark.read.parquet("/Users/zx/Desktop/parquet")
//val parquetLine: DataFrame = spark.read.format("parquet").load("/Users/zx/Desktop/pq")
parquetLine.printSchema()
//show是Action
parquetLine.show()
/**
* 写
*/
/********** 写入jdbc **********/
val props = new Properties()
props.put("user","root")
props.put("password","123568")
reslut.write.mode("ignore").jdbc("jdbc:mysql://localhost:3306/bigdata", "logs1", props)
/********** 写成text **********/
//DataFrame保存成text时出错(只能保存一列)
reslut.write.text("/Users/zx/Desktop/text")
/********** 写成json **********/
reslut.write.json("/Users/zx/Desktop/json")
/********** 写成csv **********/
reslut.write.csv("/Users/zx/Desktop/csv")
/********** 写成parquet **********/
reslut.write.parquet("hdfs://node-4:9000/parquet")
spark.stop()
}
}
Broadcast Hash Join
Shuffle Hash Join
Sort Merge Join
参考:https://www.cnblogs.com/JP6907/p/10721436.html
总结起来就是