Spark SQL介绍

Spark SQL是用于处理结构化数据的Spark组件, 结构化数据来源可以是hive, json, parquet, 或者其他RDD增加schema得到

特点

  1. 易整合, spark SQL可以与spark程序混合编程
  2. 统一的数据访问方式, 对原始数据提供一套统一的访问方式, 例如: 访问Hive,Avro, ORC, JSON等
  3. 兼容hive, 可以使用hive的HQL语句
  4. 标准的数据连接, 可以连接JDBC/ODBC
  5. 支持2种编程API, SQL方式, DSL方式(即使用DataFrame调用API)

DataFrame

DataFrame是一种按列组织的分布式数据集

DataFrame和RDD的区别:
  1. DataFrame包含了表的描述信息(schema), 多少列, 列名, 类型, 能否为空
  2. 是一种特殊的RDD, 可以理解为: RDD+ schema组成了DataFrame
  3. 主要区别就是: DataFrame带有schema元数据信息, RDD不知道数据集内部的结构. spark执行作业的时候, 可以根据数据结构信息进行计算优化, 提高运行效率

编写SparkSQL查询

配置maven的pom.xml

<dependency>
	<groupId>org.apache.spark</groupId>
	<artifactId>spark-sql_2.11</artifactId>
    <version>${spark.version}</version>
</dependency>

SparkSession的3种创建方式

// 方式1: 
val session1 = SparkSession.builder().appName("").master("local").getOrCreate()
// 方式2: 
val conf = new SparkConf().setAppName("").setMaster("local")
val session2 = SparkSession.builder.config(conf).getOrCreate
// 方式3: 可添加hive支持
val session3 = SparkSession.builder().appName("").master("local").enableHiveSupport.getOrCreate()

// 使用完成后, 注意释放资源
session.close()

RDD转换为DataFrame的3种方式

  1. 手动创建
val lineRDD:RDD = sparkContext.parallize(List(("Jim", 18),("Lily", 18)))
import sparkSession.implicits._
val dataFrame:DataFrame = lineRDD.toDF("name","age")
  1. 通过反射创建
val personRDD:RDD[Person] = xxx
import sparkSession.implicits._
val dataFrame:DataFrame = lineRDD.toDF // 无需指定字段
  1. 手动指定row和field创建
val personRDD:RDD[Row] = xxx
val schema: StructType = StructType(List(
StructField("id", LongType, true),
StructField("name", StringType, true),
StructField("age", IntegerType, true),
StructField("fv", DoubleType, true)
))
//将RowRDD关联schema
val dataFrame: DataFrame = sparkSession.createDataFrame(rowRDD, schema)

Spark SQL使用

  1. SQL方式
// 需要创建一个临时table后, 才能执行sql语句
bdf.registerTempTable("t_person")
//书写SQL(SQL方法应其实是Transformation)
val result: DataFrame = sparkSession.sql("SELECT * FROM t_person ORDER BY fv desc, age asc")
  1. DSL方式
// 无需创建临时表
val df1: DataFrame = bdf.select("name", "age", "fv")
import sqlContext.implicits._
val df2: DataFrame = df1.orderBy($"fv" desc, $"age" asc)

DataFrame转换为RDD

// 调用方法即可
val rdd:RDD[Row] = dataFrame.rdd

Dataset

从spark1.6 新加入的数据接口

使用Dataset可以方便的对字段数据进行访问, 例如: x.name, 然而在DataFrame中, 需要使用$"name"来访问, 可维护性更高

数据集的相互转换
// Dataset转RDD
val rdd:RDD[Person] = dataSet.rdd
// Dataset转DataFrame
val dataFrame = dataSet.toDF
// DataFrame转Dataset
val dataSet:DataSet[Person] = dataFrame.as[Person]

数据操作方法

DSL风格
ds.select(_.name)
ds.filter(_.age > 20)
SQL风格
sparkSession.sql("select * from table")

// session范围表, session可访问
df.createOrReplaceTempView("Person")
// 全局表, 整个应用可访问
df.createGlobalTempView("Person")
//注意, 访问全局表需要加全路径
val sql = "select * from global_temp.Person"

SPARK数据集的发展

RDD(2011) --> DataFrame(2013) --> Dataset(2015)

Dataset包含了RDD和DataFrame的功能

RDD, DataFrame, Dataset的区别

共同点:

都是spark中弹性分布式数据集

都具有transform算子和action算子, RDD具备的功能, DataFrame和Dataset基本都有

区别:

DataFrame与RDD相比, 多了schema(元数据), 数据是按列的方式存储, 类似于DB的一张表. 存储的是结构化的数据

支持更高级的API, RDD不能执行sparkSQL操作, DataFrame可以执行sparkSQL操作(SQL, DSL)

在spark2.0中, Dataset与DataFrame合并, Dataset分为强类型API和弱类型API, 强类型指的是Dataset保存的是手动创建的对象, 如:Person; 弱类型指的是保存的是Row; 具体体现在: DataFrame取特定字段, 只能通过Row.get(0)获取, 而Dataset可以使用操作对象属性的的方式获取, 这样可以在编译期间发现一些数据类型错误的问题, 并且提高编码效率

WordCount案例, SparkSQL版

"select value,count(1) from t groupby value"

各类数据源读取

// 读取JDBC数据源
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()

// 读取json
val jsons: DataFrame = spark.read.json("/Users/Desktop/json")

// 读取csv
val csv: DataFrame = spark.read.csv("c://data//t.scv")

// 读取parquet
val parquetLine: DataFrame = spark.read.parquet("c://data//t.parquet")

// 读取mysql, 写入mysql
// 封装请求MySQL的配置信息
val prop = new Properties()
prop.put("user", "root")
prop.put("password", "root")
prop.put("driver", "com.mysql.jdbc.Driver")
// 把数据写入MySQL
personDF.write.mode("append").jdbc("jdbc:mysql://node03:3306/bigdata", "person", prop)