一. Spark 新特性
- DataFrame = Dataset[Row]
- SparkSession:统一SQLContext和HiveContext,新的上下文入口
- 支持缓存和程序运行的堆外内存管理
- Accumulator功能增强:便捷api、web ui支持、性能更高
- whole-stage code generation
Spark 2.0中配备了第二代Tungsten引擎,通过在运行期间优化那些拖慢整个查询的代码到一个单独的函数中(复杂的代码可能会打包到多个函数中),消除虚拟函数的调用以及利用CPU寄存器来存放那些中间数据
其实现方式是在可能的情况下将把不同的Operator放在一起生成一个大块的处理函数。这样的好处是,去掉了冗余的operator之间的数据传递(这个可能是性能开销的大头),并且一个大的代码段不跨越函数边界,将更有可能被JVM JIT优化。终极目标是,生成的代码和手写代码有近似的速度。explain()
可以看到通过whole-stage code generation生成的代码的执行计划,*号表示自动生成的代码
eg:
select id + 1 from students where id <> 0;
复制代码
上面的Plan的计算部分将会有两个Operator:id+1
对应Projection Operator,id <> 0
对应Filter Operator。新的Spark代码生成可以将这两个部分合并生成一个大的代码块进行计算
- vectorization
只有在无法使用whole-stage code generation技术时(如action算子复杂,使用第三方组件代码),可以使用vectorization技术
核心思想是:不是一次只处理一行数据,而是将许多行的数据分别组成batches,而且采用列式格式存储;然后每个算子对每个batch进行简单的循环来遍历其中的数据。所以每次调用next()
函数都会返回一批的元组,这样可以分摊虚函数调用的开销。采用了这些措施之后,这些简单的循环也会使得编译器和CPU运行的更加高效。
vectorization仍然需要将临时数据存放在内存中而不是存放在CPU的寄存器中。所以只有在无法使用Whole-stage code-generation技术的情况下才会使用vectorization技术。用在例如Parquet Reader的解码部分 - 结构化流 Structured Streaming
1.1 spark1 VS spark2
Spark2.x重点改造的是Tungsten Engine、Dataframe/Dataset以及Structured Streaming
Spark 1.x:Spark Core(RDD)、Spark SQL(SQL+Dataframe+Dataset)、Spark Streaming、Spark MLlib、Spark Graphx
Spark 2.x:Spark Core(RDD)、Spark SQL(ANSI-SQL+Subquery+Dataframe/Dataset)、Spark Streaming、Structured Streaming、Spark MLlib(Dataframe/Dataset)、Spark Graphx、Second Generation Tungsten Engine(Whole-stage code generation+Vectorization)
1.2 RDD使用场景
- 底层操作
手动管理RDD的分区,底层调优,troubleshooting - 处理非结构化数据
如多媒体数据,文本数据 - 不使用第二代tungsten引擎提供的whole-stage code generation等性能优化技术
1.3 Dataset VS RDD
RDD的序列化机制是基于Java序列化机制或者是Kryo的,而Dataset的序列化机制基于一种特殊的Encoder来将对象进行高效序列化,以进行高性能处理或者是通过网络进行传输。
Dataset除了Encoder,也同时支持Java序列化机制,但是encoder的特点在于动态的代码生成,同时提供一种特殊的数据格式,来让spark不将对象进行反序列化,即可直接基于二进制数据执行一些常见的操作,比如filter、sort、hash等。
1.4 Dataframe/Dataset使用场景
- 需要更加丰富的计算语义,high-level的抽象语义,以及domain-specific API。
- 计算逻辑需要high-level的expression. filter. map. aggregation. average. sum. SQL. 列式存储. lambda表达式等语义,来处理半结构化或结构化的数据。
- 需要高度的编译时以及运行时的类型安全保障。
- 想要通过Spark SQL的Catalyst(SparkSQL的优化器,类似数据库引擎的执行计划优化模块)和Spark 2.x的第二代Tungsten引擎来提升性能。
- 想要通过统一的API来进行离线,流式,机器学习等计算操作。
- R或Python用户,只能使用Dataframe。
1.5 Dataframe VS Dataset
Dataframe = Dataset[Row]
- untyped API(Dataframe)
Row就是一个untyped类型的对象,因为Row是类似于数据库中的一行,只知道里面有哪些列,但是有些列即使不存在,也可以这对这些不存在的列进行操作。因此其被定义为untyped,即弱类型
DataFrame由于接近SQL的API模型,将完全享受Catalyst优化器,而原生的RDD由于过于自由的API,则无法享受这一优化
DataFrame因为解析的时候Schema还没有注入,无法完整静态类型检查,因此无法做到类型安全。 - typed API(Dataset)
Dataset[T]本身,是一种typed类型的API,其中的Object通常都是自定义的typed类型的对象,因为对象是自定义的,所以包括字段命名以及字段类型都是强类型的
DataSet支持lambda API,有类型支持并享受Catalyst优化。又由于它也有Schema支持,因此存储的时候能根据类型序列化到Native内存上(而非Java堆空间),无须使用Java Object,因此速度更快更省内存
二. spark SQL
Dataframe untyped操作
val df = spark.read.json("people.json")
df.show()
df.printSchema()
df.select("name").show()
df.select($"name", $"age" + 1).show()
df.filter($"age" > 21).show()
df.groupBy("age").count().show()
df.createOrReplaceTempView("people")
val sqlDF = spark.sql("SELECT * FROM people")
sqlDF.show()
复制代码
三. Structured Streaming
3.1 Structured Streaming与其他流式计算应用的对比
属性 | Structured Streaming | Spark Streaming | Apache Storm | Apache Flink | Kafka Stream | Google Dataflow |
Streaming API | 增量执行批处理计算 | 基于批处理计算引擎 | 与批处理无关 | 与批处理无关 | 与批处理无关 | 基于批处理计算引擎 |
基于数据位置前缀的计算完整性的保证 | √ | √ | × | × | × | × |
一致性语义 | exactly once | exactly once | exactly once | exactly once | at least once | exactly once |
事务性操作存储支持 | √ | 部分 | 部分 | 部分 | × | × |
交互式查询 | √ | √ | √ | × | × | × |
与静态数据进行join | √ | √ | × | × | × | × |
output模式
- complete mode,被更新后的整个结果表中的数据,都会被写入外部存储
- append mode,只有最近一次trigger之后,新增加到result table中的数据,会被写入外部存储。只有确定result table中已有的数据是肯定不会被改变时,才应该使用append mode。
- update mode,只有最近一次trigger之后,result table中被更新的数据,包括增加的和修改的,会被写入外部存储。
参考资料
- Spark 2.0从入门到精通