2、schema 是有StructFields 组成的StructType
6、Reserved Characters and Keywords
14、Concatenating and appending rows
一 概念预览
1、对应关系
非结构化数据 如 log files -----> Datasets
半结构化数据 如CSV files -----> DataFrames
结构化数据 如Parquet files -----> SQL tables and views
所有的Structured APIS 可以使用于 batch和streaming computation
2、DataFrames and Datasets
spark中有两种结构集合:
DataFrames
DataSets
这两种结构有微妙的区别
dataframes 和dataset 在saprk中代表 不可变 懒处理计划对于特定的数据集,可以用特定的操作用于输出
Tables 和 views 实际上和 DataFrames是一样的东西,只不过用SQL 来处理它们代替DataFrame Codes
Chapter10 详细讨论 Spark SQL
3、Schemas
定义:
schema 用来定义DataFrame的列名和类型 (colomns names and types)
4、Structured Spark Types
spark 有自己高效执行的语言。spark 用自己的Catalyst引擎来维护执行计划信息并且执行任务。换句话说,不管你用什么语言开发,spark都会转化为自己Catalyst执行器语言来执行,比如map操作很多语言都支持
1、DataFrame Vs DataSet
DataFrames Untyped
说它们无类型也不精确,主要是DataFrames 只会在运行时检查类型
对于Spark而言 DataFrames 就是Type Row类型的DataSet
DataSets Typed
会在编译时检查类型是否正确
DataSet 仅仅作用于JVM语言有效 例如Scala case classes 和Java Beans
摘录书中原话
In essence, within the Structured APIs, there are two more APIs, the “untyped”
DataFrames and the “typed” Datasets. To say that DataFrames are untyped is
aslightly inaccurate; they have types, but Spark maintains them completely and
only checks whether those types line up to those specified in the schema at
runtime. Datasets, on the other hand, check whether types conform to thespecification at compile time.
Datasets are only available to Java Virtual
Machine (JVM)–based languages (Scala and Java) and we specify types with
case classes or Java beans.
For the most part, you’re likely to work with DataFrames. To Spark (in Scala),
DataFrames are simply Datasets of Type Row. The “Row” type is Spark’s internal
representation of its optimized in-memory format for computation. This format
makes for highly specialized and efficient computation because rather than using
JVM types, which can cause high garbage-collection and object instantiation
costs, Spark can operate on its own internal format without incurring any of
those costs. To Spark (in Python or R), there is no such thing as a Dataset:
everything is a DataFrame and therefore we always operate on that optimized format
小贴士
使用DataFrame的时候相当于在,在利用spark内部调优机制
Chapter11 会对此详细解答
2、Columns
如果简单理解的话把Spark Column想象为 表格中的columns
Columns 可以代表 简单类型:如Integer,String
复杂类型:array map 或者null
3、Rows
代表一行数据记录,在DataFrame中的每行记录必须是Row类型的
可以通过SQL ,通过RDD ,通过数据源,或者直接创建
4、Spark Types
Spark 内部type和各种开发语言之间的映射
Java Types reference 注意SparkSQL 一直在优化,这些映射关系可能会变更
5、Structured Api Execution
预览
steps:
1. Write DataFrame/Dataset/SQL Code.
2. If valid code, Spark converts this to a Logical Plan.
3. Spark transforms this Logical Plan to a Physical Plan, checking for
optimizations along the way.
4. Spark then executes this Physical Plan (RDD manipulations) on the cluster
1、逻辑计划 Logical Planning
执行计划的第一步是把用户代码转换为逻辑计划
Spark利用 catalog 来分析 用户所写的原始的逻辑执行计划,如果不符合规范,将会拒绝执行计划
2、物理计划 Physical Planning
在创建好逻辑执行计划后,Spark 会 根据Physical plan 来制定不同执行策略并且通过成本模型来找出性能最高的执行方案
3、执行 Execution
在选择好物理执行计划后,spark会基于RDD进行及计算,并且会在运行时调优并把结果返回给用户
二、实际操作
接下来进入实际操作环节
创建DataFrame
1、Schemas 操作
1、schhema 具体是读取还是自己创建
schema 可以通过数据源定义schema 也可以自己显示定义 建议如下
json文件地址
https://github.com/databricks/Spark-The-Definitive-Guide/tree/master/data/flight-data
2、schema 是有StructFields 组成的StructType
StructFields 有名字、类型 或者Boolean标志 是否可以为空
spark可以指定column的元数据类型 ,元数据是存储列信息的方式
Schemas 可以包含其他StructTypes Chaper6详细介绍
2、Columns and Expressions
1、获取column方式
有很多种方式可以构造或者获取columns
但是两种最简单的方式是通过col()或者column()方法
scala提供语法糖来创建column $"myColumn"
2、明确column引用
df.col("count")
2、Expressions
什么是表达式?
对于DataFrame中的一行数据进行的一系列转换操作
expr("someCol") 和 col("comeCol")
Columns 作为表达式
落地
(((col("someCol") + 5) * 200) - 6) < col("otherCol")
和
效果是一样的
不管你使用 DataFrame方式写还是SQL方式写 最终执行都是一样的
获取一个DataFrame的columns
cloumns property
spark.read.format("json").load("/data/flight-data/json/2015-summary.json")
.columns
2、Records And Rows
定义
在spark中,each row in a DataFrame is a single record ;
Spark 用Row 类型代表一行数据,Spark用列表达式来表达Row 对象,Row Objects内部用数组字节表示。
创建Rows
只有DataFrames 拥有schemas Rows 自己是没有schemas 。如果手动创建Row,必须按照Schema的顺序指定Row中的数据类型
// in Scala
import org.apache.spark.sql.Row
val myRow = Row("Hello", null, 1, false)
获取 row中的数据
// in Scala
myRow(0) // type Any
myRow(0).asInstanceOf[String] // String
myRow.getString(0) // String
myRow.getInt(2) // Int
3、DataFrame Transformations
上面章节已经简单概述了DataFrame的组成,接下来,重点关注如何生成DataFrames
总结如下
- 添加行或者列
- 移除行或者列
- 将一行转一列
- 根据列值进行排序
1、创建DataFrames
①可以通过数据源创建DataFrames ,在Chapter9会详细介绍
并且可以创建临时视图
// in Scala
val df = spark.read.format("json")
.load("/data/flight-data/json/2015-summary.json")
df.createOrReplaceTempView("dfTable“)
②通过一组rows并且转换为DataFrame
// in Scala
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StructField, StructType, StringType, LongType}
val myManualSchema = new StructType(Array(
new StructField("some", StringType, true),
new StructField("col", StringType, true),
new StructField("names", LongType, false)))
val myRows = Seq(Row("Hello", null, 1L))
val myRDD = spark.sparkContext.parallelize(myRows)
val myDf = spark.createDataFrame(myRDD, myManualSchema)
myDf.show()
如何操作DataFrames
- select
- selectExpr
- org.apache.spark.sql.functions package 提供的函数
2、Select and SelectExpr
这两个操作 等效于你用SQL 查询一张表的数据
Because select followed by a series of expr is such a common pattern, Spark
has a shorthand for doing this efficiently: selectExpr. This is probably the most
convenient interface for everyday use:
// in Scala
df.selectExpr("DEST_COUNTRY_NAME as newColumnName", "DEST_COUNTRY_NAME").show(2)
并且,通过selectExpr 可以创建new DataFrames, 实际上可以添加任意非聚合sql 声明,
// in Scala
df.selectExpr(
"*", // include all original columns
"(DEST_COUNTRY_NAME = ORIGIN_COUNTRY_NAME) as withinCountry")
.show(2)
-- in SQL
SELECT *, (DEST_COUNTRY_NAME = ORIGIN_COUNTRY_NAME) as withinCountry
FROM dfTable LIMIT 2
Giving an output of:
3、Converting to Spark Types
4、Adding columns
5、Renaming Columns
6、Reserved Characters and Keywords
7、Case Sensitivity
8、Remove Clolumns
9、Changing a Column's Type
10、Filtering rows
11、Getting Unique Rows
12、Random samples
13、Random Splits
14、Concatenating and appending rows
15、Sorting rows
16、Limit
17、Repartition and Coalesce