文章目录
1. SparkSession相关类
1.1. DataType
DataType
是Spark SQL的所有数据类型的基本类型,Spark Sql的所有数据类型都继承自DataType,SparkSql中定义的数据类型与Java的基本数据类型大部分都是一致的。
1.2. Metadata
Metadata
用来保存StructField
的元数据信息,其本质是底层的Map[String,Any]
。Metadata
属于SparkSQL。
1.3. StructType与StructField
样例类StructField
与样例类StructType
共同构建起数据源的数据结构。
1.3.1. StructField类定义
StructField
可以理解为关系型数据表中具体某个字段属性的定义。
//StructField中共定义类4个属性:
case class StructField(
name: String, //字段名称
dataType: DataType, //数据类型
nullable: Boolean = true, //是否允许为空
metadata: Metadata = Metadata.empty //元数据)
1.3.2. StructType类定义
StructType
可以理解为关系型数据表中全部列的字段属性定义集合。
case class StructType(fields: Array[StructField]) extends DataType with Seq[StructField]
StructType
的属性中最为重要的类型为fields: Array[StructField]
,由此可以看出一个StructType中可以包括零到多个StructField。
1.4. 数据源DataSource
从SparkSQL 1.3.0
开始,Spark推出了DataFrame
的API,与此同时DataSource
也被引入到了Spark中,Spark将一系列格式的输入数据都作为数据源。
1.4.1. DataSource详解
DataSource
用于表示在SparkSQL中可插拔的数据源。DataSource
中包括以下属性:
sparkSession: SparkSession
className: String //此名称用于决定要使用的类
paths: Seq[String] = Nil //数据源的多个路径
userSpecifiedSchema: Option[StructType] = None //用户指定的StructType
partitionColumns: Seq[String] = Seq.empty //分区字段的排列
bucketSpec: Option[BucketSpec] = None //BucketSpec是一种用于将数据集分解为更多可管理部分的技术。由于桶的数量是固定的,因此数据不会随数据而波动
options: Map[String, String] = Map.empty //用于保存选项
catalogTable: Option[CatalogTable] = None //CatalogTable是用于定义表的字典
1.4.2. DataSourceRegister详解
特质DataSourceRegister
是对所有数据源的抽象,所有数据源都应该实现它。
DataSourceRegister
的所有具体实现都被注册到了DataSource
中。DataSource
将负责对不同类型数据源的查找,创建不同类型数据源的信息、解析不同数据源的关系等。
DataSourceRegister
的定义非常简单。
trait DataSourceRegister {
def shortName(): String
}
shortName()方法意在获取数据源提供者的格式或格式的别名。
1.5. 数据集合DataSet
从Spark SQL 1.3.0
版本开始在原有的SchemaRDD
的基础上提供了与R和Pandas风格类似的DataFrame
API,DataFrame
支持分布式大数据处理。
在Spark中,DataFrame
是一种以RDD为基础的分布式数据集,类似于传统数据中的二维表格。
与RDD的主要区别在于:
DataFrame
是带有Schema元数据,即DataFrame
所表示的二维数据集的每一列都带有名称和类型。
Spark SQL 1.6.0
引入了DataSet
。DataSet
是特定领域对象的强类型集合,可通过功能或关系操作进行转换。当DataSet
的泛型类型是Row
时,DataSet
还可以作为DataFrame
。
1.5.1. 属性和方法
rdd
rdd是DataSet
的属性之一,由于被关键字lazy
修饰,因此在需要rdd的值时才会进行“赖”执行。
lazy val rdd: RDD[T] = {
val objectType = exprEnc.deserializer.dataType
val deserialized = CatalystSerde.deserialize[T](logicalPlan)
sparkSession.sessionState.executePlan(deserialized).toRdd.mapPartitions { rows =>
rows.map(_.get(0, objectType).asInstanceOf[T])
}
}
ofRows
ofRows是DataSet的伴生对象中提供的方法,用于将逻辑执行计划LogicalPlan
转换为泛型是Row
的DataSet
,即DataFrame
。
多种多样的select
DataSet
提供了多个重载的select方法,以实现类似于SQL中的select语句的选择指定列功能。其它select方法都会转换为如下方法进行:
def select(cols: Column*): DataFrame = withPlan {
Project(cols.map(_.named), logicalPlan)
}
1.6. DataFrameReader详解
DataFrameReader
用于通过外部数据源的格式和数据结构加载DataSet
,有了DataFrameReader
,就可以将各种格式的数据转换为DataSet
或DataFrame
,进而以面向关系型数据的方式操纵各种格式的数据。
1.6.1. 属性和方法
DataFrameReader
只有三个属性,分别如下:
private var source: String = sparkSession.sessionState.conf.defaultDataSourceName
private var userSpecifiedSchema: Option[StructType] = None
private var extraOptions = new scala.collection.mutable.HashMap[String, String]
- source:输入数据源的格式。可通过
spark.sql.sources.default
属性配置,默认为parquet。可以通过format方法设置; - userSpecifiedSchema:用户指定的Schema。可以通过schema方法设置;
- extraOptions:用于配置一些额外的选项,通过其他方法,如jdbc方法加载数据库的中数据时设置的url等,本质上就是将key和value设置到了extraOptions中。可以通过option方法设置。
比如:timeZone (默认会话本地时区)设置一个字符串,该字符串表示一个时区,用于解析JSON/CSV数据源或分区值中的时间戳。
DataFrameReader
关键方法:
format
用于设置输入数据源的格式
def format(source: String): DataFrameReader = {
this.source = source
this
}
schema
用于设置用户指定的结构类型StructType
def schema(schema: StructType): DataFrameReader = {
this.userSpecifiedSchema = Option(schema)
this
}
多种多样的option
用于向extraOptions中添加选项,无论哪个option方法,都将转换为如下方法进行:
def option(key: String, value: String): DataFrameReader = {
this.extraOptions += (key -> value)
this
}
多种多样的load
用于将数据源的数据加载到DataFrame,其他load方法最终会转换为如下方法进行:
def load(paths: String*): DataFrame = {
sparkSession.baseRelationToDataFrame(
DataSource.apply(
sparkSession,
paths = paths,
userSpecifiedSchema = userSpecifiedSchema,
className = source,
options = extraOptions.toMap).resolveRelation())
}
根据方法实现,得知load方法首先构造DataSource
实例,然后调用DataSource
的resolveRelation方法解析得到BaseRelation
,最后调用SparkSession
的baseRelationToDataFrame方法将BaseRelation
转换为DataFrame
。
重载的text
DataFrameReader
提供了两个重载的text方法,用于设置输入数据源的格式为text并加载数据。
def text(paths: String*): DataFrame = format("text").load(paths : _*)
除了text方法,DataFrameReader
还提供了多个json、parquet等方法,用于加载不同格式的数据,这些方法都类似,最后都是通过format方法+load方法实现的。
1.7. SparkSession详解
Spark2.0
引入了SparkSession
,为用户提供了一个统一的切入点来使用Spark的各项功能。
1.7.1. 属性和方法
SparkSession的属性如下:
sparkContext
:即SparkContext
sharedState
:在多个SparkSession
之间共享的状态(包括SparkContext、缓冲的数据、监听器以及外部系统交互的字典信息)。
sessionState
:SparkSession的状态(SessionState)。SessionState中保存着SparkSession指定的状态信息。
sqlContext
:即SQLContext,SQLContext是SparkSQL的上下文信息。
conf
:类型为RuntimeConfig,是Spark运行时的配置接口类。
根据
SparkSession
的属性,SparkSession
并非是一个新创造的东西,它不过是对SparkContext、SQLContext及DataFrame等的一层封装。SparkSession的创建离不开构建器。
SparkSession的伴生对象提供了很多属性和方法,便于构造SparkSession。SparkSession的伴生对象中包含以下属性:
sqlListener
:类型定义为AtomicReference[SQLListener]
,用于持有SQLListener
。SQLListener
主要用于SQL UI。
activeThreadSession
:类型定义为InheritableThreadLocal[SparkSession]
,用于持有当前线程的激活的SparkSession。SparkSession的伴生对象提供了setActiveSession(session: SparkSession)、getActiveSession、clearActiveSession()方法分别用于设置、获取、清空activeThreadSession中持有的SparkSession
defaultSession
:类型定义为AtomicReference[SparkSession]
,用于持有默认的SparkSession。SparkSession的伴生对象提供了setDefaultSession(session: SparkSession)、getDefaultSession、clearDefaultSession()方法分别用于设置、获取、清空defaultSession中持有的SparkSession。
SparkSession的方法如下:
builder
SparkSession的伴生对象中提供了builder方法用于创建Builder
read
SparkSession的read方法用于创建DataFrameReader
baseRelationToDataFrame
SparkSession的baseRelationToDataFrame方法用于将BaseRelation转化为DataFrame,将BaseRelation转换为DataFrame后,就可以使用操作关系数据的方式来开发了。
1.8. SparkSession的构建器Builder
Builder
是SparkSession
实例的构建器,对SparkSession
实例的构造都依赖于它。
1.8.1. 属性和方法
- options:HashMap[String, String]属性用于缓冲构建
SparkConf
所需的属性配置。 - userSuppliedContext属性用于持有用户提供的
SparkContext
,可以通过Builder的sparkContext(sparkContext: SparkContext)
的方法来设置。
多种多样的config方法
Builder提供了多个重载的config方法,用于向options属性中添加配置。根据声明options时指定的泛型,可以知道Builder应当提供一个向options中添加key和value都是字符串的方法。
def config(key: String, value: String): Builder = synchronized {
options += key -> value
this
}
Builder还提供了很多将其他基本类型转换为字符串后添加到options的方法。此外Builder提供的appName(name: String)、master(master: String)、enableHiveSupport()方法也都是通过config方法实现的。
getOrCreate方法
用于获取或者创建SparkSession