开发者学堂课程【大数据 Spark 2020版(知识精讲与实战演练)第三阶段:扩展_Catalyst 优化器_优化过程】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/690/detail/12040
扩展_Catalyst 优化器_优化过程
Catalyst 优化器_优化过程
为了解决过多依赖 Hive 的问题, SparkSQL 使用了一个新的 SQL 优化器替代 Hive 中的优化器,这个优化器就是 Catalyst ,整个 SparkSQL 的架构大致如下:
1.API 层简单的说就是 Spark 会通过一些 API 接受 sQL 语句
2.收到 SQL 语句以后,将其交给 Catalyst, Catalyst 负责解析 sQL,生成执行计划等
3.Catalyst 的输出应该是 RDD 的执行计划
4.最终交由集群运行
大致步骤是 Spark SQL 的 API,SQL 的 API,大致有两种,一种是声明式的,还有一种是命令式的,两种 API 都可以,两种 API 在调用过了以后,其调用的结果会被传入 catalyst,catalyst 会根据你传入进来的一些 API 一些结果,生成对应的执行计划,执行计划生成的时候,会经历大致四个阶段,第一个阶段就是解析,第二个阶段是优化,第三个阶段是运行,就是物理计划,总共是三个大阶段,然后第四个阶段是运行。
运行的时候,就会给其放入这个 RDD 当中,最终在我们到这个 catalyst 当中去运行,这是 catalyst 的工作的一个大致的步骤。
我们把视角放在 catalyst 这个东西之上,直接去看这个 catalyst 是怎么工作的,它里面都有什么样的一些步骤。
首先第一步,解析 SQL。一般情况下,编译器里面最常做的一件事情就是先去解析,传进来的这个编程语言,比如说 Java 这些都是一样的。他们如果编译器的话,要先根据你的这个代码来去生成一棵语法树,这棵树里面就包含了你从底层到上层所做的所有事情,生成这样的一棵树以后,Catalyst 会做什么样的工作呢
Catalyst 会在第二步,向这棵树里面添加一些对应的一些元素,添加一些这个结构化的一些信息,比如说我们来看这棵树。
第一步去读取 People 的这样的一张表,第二个步骤要读取 score 这样的一张表,然后对其进行着完以后 filter, filter 完以后,Project 就是筛选某一列,最终 aggregate 就是聚合得到结果,这是我们的一棵树,在这棵树当中,我们整个的步骤首先,对于第一个地方,这个 filter 的地方,要有一些代码的执行,要知道你要去判断什么样的 filter,我们这个地方的判断,就是判断 people ID 等于 score ID,并且 people 的 age 大于十岁,看一下这个 SQL 语句,做的就是这样的事情。
第二大步骤,加入数据信息数据的元素。
在这个位置,本来是一个 people ID,不知道他是什么类型,SKY 不知道它是什么类型,不知道这个 age 是什么类型,第一步需要为 score ID 生成一个新的标识,首先他叫 ID,然后,第一个就是他的 ID,这个列的 ID。
接下来,在 project 这个地方,取出 score math 再加上 180,如果是这样,math 其实也会被转换,转换成 Mascot#2。2 就是 math score 的标识,是一个 L 类型,根据这样的一个步骤,就可以为这个 ast 当中加入一些这个标识符,一些类型信息,一些结构信息。有了结构信息以后,就可以对其来进行优化。
l score.id - id#1#L 为 score.id 生成 id 为 1,类型是 Long
l score.math_score - math_score#2#L 为 score.math_score 生成 id 为 2,类型为 Long
l people.id - id#3#L 为 people.id 生成 id 为 3,类型为 Long
l people.age - age#4#L 为 people.age 生成 id 为 4,类型为 Long
一般情况下,这个优化指的都是按照规则进行优化,也就是比较死板的一种优化方式,我们会先通过一些规则来去看你符合这个规则,如果你符合这个规则,就来进行优化。
比如说这样的一棵树,在我们的 John 之后做了一个 filter,如果我们把这个 filter 挪到 John 之前呢?也就是在 scan 以后直接 filter,join 的数据就变少,这种优化方式叫做谓词下推,谓词下推的这种优化方式,它的优势就是在于减少数据量,这个 catalyst 会先去看你符合这样的一个方式,只要他去看一看这个 filter 前面是不是有这样的一个 join。
如果有的话,是否会影响你的结果,如果不影响,把 filter 下推一下,推到 scan 的后面,把这个 filter 也往下推一下,推到 scan 的后面,所以这时,就要留在这个位置,也就是说本来就变到了这个位置,本来 filter 到了后面,所以,这是谓词下推。
怎么做到的呢?是通过规则的匹配来做到的,符合这个规则,就推一下。
除了谓词下推以外,我们还有一个叫做裂值裁剪,、假设说你现在执行的一个 SQL 是这样的,一个 select 的 name,只取了一列,这个 person 中有十列,我们应该把这个 project 也往下推,只要这一列,后面所有的操作基本上都是围绕这一切来,假如说后面的一些操作是围绕着一列来的,其他的数据就没有必要参与那些操作,这棵树会变成这个样子。
首先,我们通过规则匹配到这个 project,在这个位置,是有影响的,也就是说这个 project 可以推到这个位置,通过一些规则匹配,这个 project 你可以理解为就是 select,然后,select 的操作,就会被推到我们的 Join 和 filter,这个时候,project 就会被优化,传到 join 的数据,就再一次变少了。
这是我们所说的两种显著的优化方式,一个叫做谓词下推,一个叫做列词裁剪。
这个时候我们生成的还没有办法直接运行,因为生成的是一个逻辑计划,把这个数怎么放到集群里运行?
要把这棵树最终要翻译成什么,翻译成我们的 RDD 才能去运行到集群,这一步就叫做逻辑计划生成为物理计划,根据这样的一棵树生成物理计划,一颗优化过的树生成物理,就是物理计划,最终去调度这个 ID 的去运行,这就是我们 Catalyst 的一个大致的原理。





