标签:第一步 强类型 就是 orm 带来 ons 相同 内部使用 是你
?可以看到这个最终执行的时候分分成了两个 stage, 把小表 broeadcastExechage 到了大表上做?BroadcastHashJoin, 没有进化 shuffle 操作,然后最后一步聚合的时候,先在 map 段进行了一次 HashAggregate sum 函数, 然后 Exchage 操作根据 name 把相同 key 的数据 shuffle 到同一个分区,然后做最终的 HashAggregate sum?操作,这里有个 WholeStageCodegen 比较奇怪,这个是干啥的呢,因为我们在执行 Filter ,Project 这些 operator 的时候,这些 operator 内部包含很多? Expression, 比如?SELECT sum(v),name, 这里的 sum 和 v 都是 Expression,这里面的 v 属于 Attribute 变量表达式,表达式也是树形数据结构,sum(v) ?就是 sum 节点和 sum 的子节点 v 组成的一个树形结构,这些表达式都是可以求值和生成代码的,表达式最基本的功能就是求值,对输入的 Row 进行计算 , Expression 需要实现?def eval(input: InternalRow = null): Any?函数来实现它的功能。
?
表达式是对 Row 进行加工,输出的可以是任意类型,但是 Project 和 Filter 这些 Plan 输出的类型是?def output: Seq[Attribute], 这个就是代表一组变量,比如我们例子中的?Filter (age >= 11) 这个plan, 里面的?age>11 就是一个表达式,这个 > 表达式依赖两个子节点, 一个Literal常量表达式求值出来就是 11, 另外一个是?Attribute 变量表达式 age, 这个变量在 analyze 阶段转变为了?AttributeReference 类型,但是它是Unevaluable,为了获取属性在输入 Row 中对应的值, 还得根据 schema 关联绑定一下这个变量在一行数据的 index, 生成 BoundReference,然后?BoundReference 这种表达式在 eval 的时候就可以根据 index 来获取 Row 中的值。??age>11 这个表达式最终输出类型为 boolean 类型,但是 Filter 这个 Plan 输出类型是?Seq[Attribute] 类型。
?
可以想象到,数据在一个一个的 plan 中流转,然后每个 plan 里面表达式都会对数据进行处理,就相当于经过了一个个小函数的调用处理,这里面就有大量的函数调用开销,那么我们是不是可以把这些小函数内联一下,当成一个大函数,WholeStageCodegen 就是干这事的。
?
?
可以看到最终执行计划每个节点前面有个 * 号,说明整段代码生成被启用,在我们的例子中,Filter, Project,BroadcastHashJoin,Project,HashAggregate 这一段都启用了整段代码生成,级联为了两个大函数,有兴趣可以使用 a.queryExecution.debug.codegen 看下生成后的代码长什么样子。然而 Exchange 算子并没有实现整段代码生成,因为它需要通过网络发送数据。
?
我今天的分享就到这里,其实 spark sql 里面有很多有意思的东西,但是因为问题的本质复杂度,导致需要高度抽象才能把这一切理顺,这样就给代码阅读者带来了理解困难, 但是你如果真正看进去了,就会有很多收获。如果对本文有任何见解,欢迎在文末留言说出你的想法。br/>??
**牛人说**
?
「牛人说」专栏致力于技术人思想的发现,其中包括技术实践、技术干货、技术见解、成长心得,还有一切值得被发现的内容。我们希望集合最优秀的技术人,挖掘独到、犀利、具有时代感的声音。
?
投稿邮箱:marketing@qiniu.com
?
?
?
标签:第一步 强类型 就是 orm 带来 ons 相同 内部使用 是你
原文地址:http://blog.51cto.com/7741292/2320031