主要内容:

  • 介绍RDD和DataFrame

1、思考?

Spark 3.0 大版本发布,Spark SQL 的优化占比将近 50%;而像 PySpark、Mllib 和 Streaming 的优化占比都不超过 10%,Graph 的占比几乎可以忽略不 计。这是否意味着 Spark 社区逐渐放弃了其他计算领域,只专注于数据分析?为什么需要 Spark SQL 这个新一代引擎内核?Spark Core 有什么问题吗?Spark SQL 解决了 Spark Core 的哪些问题?怎么解决的?

2、分析

2.1 RDD之痛:优化空间受限

自从Spark1.3发布了DataFrame,它就开始代替RDD,逐渐成为开发者的首选。一般情况下,新抽象的诞生一定是为了解决旧抽象不能搞定的问题,那么RDD存在哪些问题呢?

在RDD的开发框架下,我们可以调用RDD算子(Transformation、Action算子)的排列组合就可以实现业务逻辑。如map、mapPartitions、filter、flatMap、reduceByKey、aggregateByKey、foreach等算子,它们都是高阶函数。高阶函数指的是形参包含函数的函数,或者返回结果包含函数的函数,也可称为“高阶算子”。对于这些高阶算子,开发者需要以Lambda函数的形式自行提供具体的计算逻辑。以map为例,我们需要明确对那些字段做映射,以什么规则映射;对于filter算子,需要指明以什么条件在哪些字段上过滤。而Spark只知道开发者要做map、filter,但是并不知道具体怎么做map和filter。即在Spark Core的开发模式下,Spark Core只知道做什么,而不知道该怎么做。这会让Spark Core两眼一抹黑,除了把Lambda函数用闭包的形式发送到Executor以外,实在是没有什么额外的优化空间

2.2 DataFrame应运而生

DataFrame的特点是什么,它和RDD又有什么不同呢?

DataFrame就是携带数据模式Schema的结构化分布式数据集,而RDD是不带Schema的分布式数据集。因此,从数据表示的角度来看,是否携带Schema就是二者的唯一区别。带Schema的数据表示形式决定了DataFrame只能封装结构化数据,而RDD则没有这个限制,所以除了结构化数据,RDD还能封装半结构化数据和非结构化数据。其次,从开发API上看,RDD算子多是高阶函数,这些算子允许开发者灵活地实现业务逻辑,表达能力更强。

DataFrame的表达能力相比较弱:

  • DataFrame定义了一套DSL(Domain Specific Language)算子,如select、filter、agg、groupBy等等。由于DSL语言是为了解决某一类任务而专门设计的计算机语言,表达能力非常有限。
  • DataFrame中的绝大多数算子都是标量函数,它们的形参往往是结构化的数据列,表达能力也很弱。

你可能会问:“相比RDD,DataFrame的表示和表达能力都变弱了,那它是怎么解决RDD优化空间受限的核心痛点呢?”当然,仅凭DataFrame在API上的改动就想解决RDD的核心痛点是不可能的。DataFrame API最打的意义在于,它为Spark引擎的内核优化打开了全新的空间

  • 首先,DataFrame中的Schema所携带的类型信息,让Spark可以根据明确的字段类型设计定制化的数据结构,从而大幅提升数据的存储和访问效率。
  • 其次,标量算子确定的计算逻辑,让Spark可以基于启发式的规则和策略,甚至是动态的运行时信息,去优化DataFrame的计算过程。

2.3 Spark SQL

为了支持DataFrame开发模式,Spark从1.3开始推出Sparl SQL。Spark SQL的核心组件:

  • Catalyst
  • Tungsten

Catalyst和Tungsten才是负责引擎内核优化的幕后英雄。

2.4 Catalyst 执行过程优化

  • Unresolved Logical Plan转换成Analyzed Logical Plan:基于确切的计算逻辑,Spark会使用第三方的ANTLR生成抽象语法树(AST, Abstract Syntax Tree)。树的节点是标量算子的处理逻辑(select、filter等),树的边携带的数据的信息(表和字段)。在Spark当中,语法树还有个别名叫“Unresolved Logical Plan”,正是Catalyst优化过程的起点。Catalyst做的第一步优化,就是结合DataFrame的Schema信息,确认逻辑计划中的表名、字段名、字段类型与实际数据是否一致。
  • 基于Analyzed Logical Plan,Catalyst利用启发式的规则和执行策略把逻辑计划转化为可执行的物理执行计划。Catalyst的优化空间来源DataFrame的开发模式。

2.5 Tungsten 数据结构优化

Tungsten使用定制化的数据结构Unsafe Row来存储数据,其优点是存储效率高,GC效率高。Tungsten之所以设计成这样的数据结构,仰仗的就是DataFrame携带的Schema信息。

3、总结

基于DataFrame简单的标量算子和明确的Schema定义,借助Catalyst优化器和Tungsten,Spark SQL有能力在运行时构建起一套端到端的优化机制。这套机制运用启发式的规则和策略,以及运行时的执行信息,将原本次优、甚至是低效的查询计划转化为高效的执行计划,从而提升端到端的执行性能。在 DataFrame 的开发模式下,所有子框架、以及 PySpark,都运行在 Spark SQL 之上, 都可以共享 Spark SQL 提供的种种优化机制,这也是为什么 Spark 历次发布新版本、 Spark SQL 占比最大的根本原因。