SparkSQL源码解析 Analyzer

Unresolved LogicalPlan

经过 AstBuilder 的处理,可以将实例SQL所对应的抽象语法树解析为逻辑算子树 Unresolved LogicalPlan。逻辑算子树中未被解析的有 UnresolvedRelation 和 UnresolvedAttribute 两种对象。实际上, Analyzer 所起到的主要作用就是将这两种节点或表达式解析成有类型的(Typed)对象。 在此过 程中,需要用到 Catalog 和Rule的相关信息。 Catalog有关信息可查看https://blog.csdn.net/qq_41775852/article/details/105157879

Rule

在 Unresolved LogicalPlan 逻辑算子树的操作(如绑定、解析、优化等)中,主要方法都是基于规则(Rule)的,通过 Scala 语言模式匹配机制(Pattern-match)进行树结构的转换或节点改写。 Rule 是一个抽象类,子类需要复写 apply(plan: TreeType)方法来制定特定的处理逻辑,基本定义如下:
在这里插入图片描述

示例

例如ResolveInlineTables将Unresolved LogicalPlan逻辑算子树中的UnresolvedInlineTable解析为LocalRelation。
在这里插入图片描述
其apply方法传入LogicalPlan参数。然后调用LogicalPlan的resolveOperators 方法。此方法位于trait AnalysisHelper之中,LogicalPlan继承了此trait
在这里插入图片描述
除了resolveOperators方法,AnalysisHelper还有众多方法可以在Rule的apply方法中被LogicalPlan调用,其都会返回已经应用过rule的LogicalPlan。

  • resolveOperators:Returns a copy of this node where rule has been recursively applied to the tree. When rule does not apply to a given node, it is left unchanged.
  • resolveExpressions:Recursively transforms the expressions of a tree, skipping nodes that have already been analyzed.
  • transformXXX:调用TreeNode.transformXXX(rule),其与resolveOperators的区别在于transformXXX不会跳过已经analyzed的子树。

在这里插入图片描述
resolveOperators接收一个偏函数参数rule(此偏函数就是Rule类定义的具体解析方法),调用resolveOperatorsDown函数,并将偏函数rule作为参数传入。偏函数具体定义可参考:https://blog.csdn.net/bluishglc/article/details/50995939
在这里插入图片描述
resolveOperatorsDown代表从上向下的遍历逻辑算子树,对树中各个节点的LogicalPlan应用rule(即偏函数),对其进行analyze解析,最后返回遍历analyze之后的LogicalPlan。

analyzed为AnalysisHelper变量,analyzed如果为true,表示此节点以及所有的子节点已经analysis和verification,其用来避免再次analyze已经analyzed过的树。
在这里插入图片描述

所有Rule的应用过程如上述。调用Rule子类的apply方法传入LogicalPlan参数(可通过类名()直接调用apply())。Rule子类的apply方法中定义偏函数rule表示具体的解析规则,调用LogicalPlan的resolveOperator或resolveExpressions函数,将偏函数rule传入。LogicalPlan的resolveXXX方法,自上而下或自下而上的对逻辑算子树进行遍历,并应用偏函数rule,最后得到经过rule解析之后的LogicalPlan。

RuleExecutor

有了各种具体规则后,还需要驱动程序来调用这些规则,在 Catalyst 中这个功能由 RuleExecutor 提供。 凡是涉及树型结构的转换过程(如 Analyzer 逻辑算子树分析过程、 Optimizer 逻辑算子树的优化过程和后续物理算子树的生成过程 等),都要实施规则匹配和节点处理,都继承自 RuleExecutor[TreeType]抽象类。
在这里插入图片描述
RuleExecutor 内部提供了一个 Seq[Batch],里面定义的是该 RuleExecutor 的处理步骤。每个 Batch 代表一套规则 Rule[TreeType]*,配备一个策略Strategy,该策略说明了迭代次数(一次还是多次)。

RuleExecutor 的execute(plan: TreeType): TreeType 方法会按照 batches 顺序和 batch 内的 Rules 顺序,对传入的 plan 里的节点进行迭代处理,处理逻辑由具体 Rule 子类实现。
在这里插入图片描述
如图rule(plan)会调用Rule类的apply方法对LogicalPlan进行解析,过程已经在上叙述。

batch中的某一个rule对逻辑算子树遍历之后,并不能够一定保证逻辑算子树中的所有符合规则的节点都应用了此rule。因为某些rule在对LogicalPlan进行解析时,必须保证此节点的子节点已经处于resolved状态(LogicalPlan的变量,表示LogicalPlan中所有的expression已经被解析过了)。如果子节点还没有处于resolved状态,那么跳过此节点。

例如对于下面的Unresolved LogicalPlan调用ResolveReferences规则时,可以解析Filter中的age属性,因为 Filter 的子节点 Relation 已经处于 resolved 状态。而在对 Project 中的表达式 name 属性进行分析时,因为 Project 的子节点四ter 此时仍然处于 unresolved 状态(注:虽然 age 列完 成了分析,但是整个 Filter 节点中还有“18”这个 Literal 常数表达式未被分析),因此解析操作无法成功。

在这里插入图片描述
所以对于同一各batch的的rules,其会不断循环对逻辑算子树进行应用解析,直到超过了一定次数batch.strategy.maxIterations,或者batch中的rules应用之后,逻辑算子树没有变化,才会进入下一个batch的rules应用解析。当所有batch都应用完之后,executor函数才结束。
在这里插入图片描述

Analyzer

Analyzer继承自 RuleExecutor 类,其会调用父类 RuleExecutor 中实现的executor()方法进行Unresolved LogicalPlan逻辑算子树的解析。主要的不同之处是 Analyzer 中重新定义了一系列规则,即 RuleExecutor 类中的成员变量 batches。
在这里插入图片描述
在 Spark 2.1 版本中, Analyzer 默认定义了 6 个 Batch,共有 34 条内置的规则外加额外实现的扩展规则(图 中 extendedResolutionRules)。

  1. Batch Substitution
    Substitution 含义是替换,因此这个 Batch 对节点的作用类似于替换操作。 目前 在 Substitution 这个 Batch 中,定义了 4 条规则,分别是 CTESubstitution、 WindowsSubstitution、 Eliminate Unions 矛刀 SubstituteUnresolvedOrdinals。
  2. Batch Resolution
    该 Batch 中包含了 Analyzer 中最多同时也最常用的解析规则,如表所示。 表中规则从上 到下的顺序也是规则被 RuleExecutor 执行的顺序。
    在这里插入图片描述
  3. Batch Nondeterministic =》 PullOutNondeterministic
    该 Batch 中仅包含 PullOutNondeterministic 这一条规则, 主要用来将 LogicalPlan 中非 Project或非 Filter 算子的 nondeterministic (不确定的)表达式提取出来,然后将这些表达式放在内层 的 Project 算子中或最终的 Project 算子中。
  4. Batch UDF =》 HandleNulllnputsForUDF
    对于 UDF 这个规则, Batch 主要用来对用户自定义函数进行一些特别的处理,该 Batch 在 Spark2.l 版本中仅有 HandleNullinputsForUDF 这一条规则。 HandleNullinputsForUDF 规则用来处 理输入数据为 Null 的情形,其主要思想是从上至下进行表达式的遍历(transformExpressions Up) , 当匹配到 ScalaUDF 类型的表达式时,会创建 If表达式来进行 Null 值的检查。
  5. Batch FixNullability =》 FixNullability
    该 Batch 中仅包含 FixNullability 这一条规则,用来统一设定 LogicalPlan 中表达式的 nullable 属性。 在 DataFrame 或 Dataset 等编程接口中,用户代码对于某些列(AttribtueReference)可能会改变其 nullability 属性,导致后续的判断逻辑(如 isNull 过滤等)中出现异常结果。 在 FixNullability 规则中,对解析后的 LogicalP!an 执行 transformExpressions 操作,如果某列来自于 其子节点,则其 nullabikity 值根据子节点对应的输出信息进行设置。
  6. Batch Cleanup =》 CleanupAliases
    该 Batch 中仅包含 CleanupAliases 这一条规则,用来删除 Logica!Plan 中无用的别名信息。 一般情况下,逻辑算子树中仅 Project、 Aggregate 或 Window 算子的最高一层表达式(分别 对应 project list、 aggregate expressions 和 window expressions)才需要别名。 CleanupAliases 通过 trimA!iases 方法对表达式执行中的别名进行删除。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android apk分析器(ApkAnalyzer)是一个用于分析和查看Android应用程序(apk文件)的工具。它可以帮助开发者深入了解应用程序的内部结构和信息,以便在开发和调试过程中提供更多的支持。 ApkAnalyzer的源代码是开放的,由Android开源社区提供。它使用Java编程语言编写,使用了Android SDK中的相关类库和工具,如aapt、dex2jar等。 ApkAnalyzer的主要功能包括: 1. 分析APK文件的内容:ApkAnalyzer可以解析APK文件的目录结构和资源文件,从而了解应用程序的组织结构和内容。它可以展示应用程序的AndroidManifest.xml文件、资源文件、dex文件等。 2. 查看应用程序的权限:ApkAnalyzer可以显示应用程序在AndroidManifest.xml文件中声明的权限信息,帮助用户了解应用程序需要访问的敏感权限。 3. 显示应用程序的依赖项:ApkAnalyzer可以分析APK文件中包含的库文件和依赖项,帮助开发者了解应用程序所使用的第三方库和组件。 4. 反编译应用程序的代码:ApkAnalyzer可以将应用程序的dex文件反编译为Java源代码,使得开发者能够查看和分析应用程序的代码逻辑和实现细节。 5. 检查APK文件的大小和资源使用情况:ApkAnalyzer可以统计应用程序使用的资源文件和文件大小,帮助开发者优化应用程序的性能和包大小。 总之,Android ApkAnalyzer源码是一个非常有用的工具,它提供了一种便捷的方式来分析和了解Android应用程序的内部结构和信息。开发者可以通过阅读源码了解其实现细节,并根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值