互联网

Spark SQL Catalyst优化器

作者:永利官网    发布时间:2020-01-10 02:25     浏览次数 :196

[返回]

图片 1

笔录一下个体对sparkSql的catalyst那么些函数式的可扩大的询问优化器的掌握,目录如下,

ROWID: 表中的每大器晚成行在数据文件中都有叁个大意地址,ROWID伪列再次来到的正是该行的物理地址。使用ROWID能够长足的平昔表中的某生龙活虎行,ROWID值能够唯风流浪漫的标记表中的生机勃勃行,由于ROWID重临的是该行的情理地址,因而利用ROWID能够彰显行是如何存款和储蓄的。

SQL优化是大家平常会蒙受的标题,无论你是专职的数码深入剖析人士只怕全栈开采大神或然是CUXC90D搬运工。

0. Overview
1. Catalyst工作流程
2. Parser模块
3. Analyzer模块
4. Optimizer模块
5. SparkPlanner模块
6. Job UI
7. Reference

SELECT ROWID, ename FROM emp WHERE sal > 2000;

作者们在职业中平日会听到这么的响声:“查询慢?加个索引吧”。纵然加索引并不一定能解决难题,不过那反映了SQL优化的沉凝。


 

而数据库着重由三片段构成,分别是解析器、优化器和举办引擎。

Overview

斯ParkerSQL的着力是Catalyst优化器,是以黄金时代种流行性的方法选拔Scala的的形式相称和quasiquotes建制来塑造的可扩充查询优化器。

图片 2

sparkSql pipeline

sparkSql的catalyst优化器是百分百sparkSql pipeline的中间宗旨部分,其实行战略首要两大方向,

  1. 基于准绳优化/Rule Based Optimizer/RBO
    • 后生可畏种资历式、启迪式优化思路
    • 对于着力优化算子join有一点点不可能,如两张表实施join,到底使用broadcaseHashJoin照旧sortMergeJoin,近来sparkSql是因此手工业设定参数来规定的,假诺一个表的数据量小于某些阈值(暗中认可10M?)就应用broadcastHashJoin
      • nestedLoopsJoin,P,Q双表两个循环, O(M*N)
      • sortMergeJoin是P,Q双表排序后相互作用游标
      • broadcastHashJoin,PQ双表中小表放入内部存款和储蓄器hash表,大表遍历O(1State of Qatar格局取小表内容
  2. 基于代价优化/Cost Based Optimizer/CBO
    • 针对各种join评估当前两张表使用每一个join战略的代价,依照代价揣测明确朝气蓬勃种代价最小的方案
    • 不同physical plans输入到代价模型(前段时间是总括),调度join顺序,减弱中间shuffle数据集大小,达到最优输出

ROWNUM: 在查询的结果聚集,ROWNUM为结果聚集每少年老成行标记二个行号,第生机勃勃行重返1,第二行再次来到2,就那样推算。通过ROWNUM伪列能够限定查询结果集中重返的行数。

其实施逻辑是我们输入的SQL语句通过深入分析器解析成关系表达式,通过优化器把涉及表达式调换来试行陈设,最后通超过实际施引擎实行实行。所以优化器在超大程度上主宰了贰个类别的个性。优化器的成效就好比找到两点时期的最短路线。

Catalyst专门的学业流程

  • Parser,利用ANTLR将sparkSql字符串深入分析为架空语法树AST,称为unresolved logical plan/ULP
  • Analyzer,依靠于数据元数据catalog将ULP拆解深入分析为logical plan/LP
  • Optimizer,依照各样RBO,CBO优化战术得到optimized logical plan/OLP,紧尽管对Logical Plan实行剪枝,合并等操作,进而删除掉风华正茂部分不行总结,或对大器晚成部分计量的多个步骤举办联合

SELECT ROWNUM, ename, job, sal FROM emp WHERE ROWNUM <= 5; // 取前5名职员和工人的新闻

上篇随笔大家提到了Calcite,Calcite自身就补助三种优化措施分别是RBO和CBO。

other

Optimizer是catalyst工作后期了,前边生成physical plan以至实践,首假诺由sparkSql来产生。

  • SparkPlanner
    • 优化后的逻辑实践布置OLP依然是逻辑的,并不能够被spark系统明白,那时急需将OLP转变到physical plan
    • 从逻辑布署/OLP生成一个或三个概略试行陈设,基于花销模型cost model从当中采取多少个
  • Code generation
    • 生成Java bytecode然后在每后生可畏台机械上实施,形成福睿斯DD graph/DAG

SELECT ROWNUM, T.* FROM

RBO

Parser模块

将sparkSql字符串切分成二个多少个token,再依赖早晚语义法规拆解深入分析为三个虚无可奈何法树/AST。Parser模块近期着力都利用第三方类库ANTL奥迪Q3来促成,举个例子Hive,presto,sparkSql等。

图片 3

parser切词

Spark 1.x本子接收的是Scala原生的Parser Combinator构建词法和语法解析器,而斯Parker2.x版本选取的是第三方语法深入分析器工具ANTLKoleos4。

Spark2.x SQL语句的剖析选取的是ANTL索罗德4,ANTLLAND4根据语Hungary语件SqlBase.g4电动解析生成多个Java类:词法解析器SqlBaseLexer和语法解析器SqlBaseParser。

SqlBaseLexer和SqlBaseParser都以运用ANTLHighlander4自动生成的Java类。使用那多少个拆解剖析器将SQL字符串语句剖析成了ANTLEvoque4的ParseTree语法树布局。然后在parsePlan进程中,使用AstBuilder.scala将ParseTree调换来catalyst表明式逻辑布置LogicalPlan。


(SELECT ename, job, sal FROM emp ORDER BY sal DESC) T

RBO(Rule-Based Optimizer卡塔尔基于法则的优化器。是依照已经制定好的有个别优化准则对关系表达式举办改造,最后生成八个最优的执行安排。它是大器晚成种资历式的优化措施,优化法规都以事前定义好的,只要求将SQL遵照优化准则的顺序往上套就能够,生龙活虎旦满意有些法则则进行优化。

Analyzer模块

经过深入分析后ULP有了基本骨架,然则系统对表的字段新闻是不亮堂的。如sum,select,join,where还应该有score,people都意味着什么意义,那个时候内需着力的元数据信息schema catalog来表明那一个token。最重大的元数据消息正是,

  • 表的schema信息,主要不外乎表的宗旨概念(表名、列名、数据类型)、表的数码格式(json、text、parquet、压缩格式等)、表的物理地点
  • 基本函数新闻,首借使指类消息

Analyzer会再一次遍历整个AST,对树上的各个节点举办数据类型绑定以及函数绑定,举例people词素会遵照元数据表消息深入分析为带有age、id以致name三列的表,people.age会被剖析为数据类型为int的变量,sum会被深入深入分析为一定的聚合函数,

图片 4

词义注入

//org.apache.spark.sql.catalyst.analysis.Analyzer.scala
  lazy val batches: Seq[Batch] = Seq( //不同Batch代表不同的解析策略
    Batch("Substitution", fixedPoint,
      CTESubstitution,
      WindowsSubstitution,
      EliminateUnions,
      new SubstituteUnresolvedOrdinals(conf)),
    Batch("Resolution", fixedPoint,
      ResolveTableValuedFunctions ::
      ResolveRelations ::  //通过catalog解析表或列基本数据类型,命名等信息
      ResolveReferences :: //解析从子节点的操作生成的属性,一般是别名引起的,比如people.age
      ResolveCreateNamedStruct ::
      ResolveDeserializer ::
      ResolveNewInstance ::
      ResolveUpCast ::
      ResolveGroupingAnalytics ::
      ResolvePivot ::
      ResolveOrdinalInOrderByAndGroupBy ::
      ResolveMissingReferences ::
      ExtractGenerator ::
      ResolveGenerate ::
      ResolveFunctions :: //解析基本函数,如max,min,agg
      ResolveAliases ::
      ResolveSubquery :: //解析AST中的字查询信息
      ResolveWindowOrder ::
      ResolveWindowFrame ::
      ResolveNaturalAndUsingJoin ::
      ExtractWindowExpressions ::
      GlobalAggregates :: //解析全局的聚合函数,比如select sum(score) from table
      ResolveAggregateFunctions ::
      TimeWindowing ::
      ResolveInlineTables ::
      TypeCoercion.typeCoercionRules ++
      extendedResolutionRules : _*),
    Batch("Nondeterministic", Once,
      PullOutNondeterministic),
    Batch("UDF", Once,
      HandleNullInputsForUDF),
    Batch("FixNullability", Once,
      FixNullability),
    Batch("Cleanup", fixedPoint,
      CleanupAliases)
  )

WHERE ROWNUM <= 5卡塔尔(قطر‎; // 取薪俸最高的前5名

这样的结果正是平等一条SQL,无论读取的表中的多寡是何许的,最终身成的进行陈设都以同等的。并且SQL的写法分裂也很有十分大概率影响最终的实行安顿,进而影响SQL的性格(基于优化准则顺序实践卡塔尔国。

Optimizer模块

Optimizer是catalyst的核心,分为RBO和CBO两种。
RBO的优化战术正是对语法树举办二次遍历,方式相配能够满意特定准则的节点,再进行相应的等价转换,将在风流倜傥棵树等价地转变为另意气风发棵树。SQL中经典的大范围优化法规有,

  • 谓词下推(predicate pushdown)
  • 常量累计(constant folding)
  • 列值裁剪(column pruning)
  • Limits合并(combine limits)

图片 5

由下往上走,从join后再filter优化为filter再join

图片 6

从`100+80`优化为`180`,幸免每一条record都亟待奉行贰遍`100+80`的操作

图片 7

剪裁无需的字段,特别是嵌套里面包车型客车没有必要字段。如只需people.age,无需people.address,那么能够将address字段吐弃

//@see http://blog.csdn.net/oopsoom/article/details/38121259
//org.apache.spark.sql.catalyst.optimizer.Optimizer.scala
  def batches: Seq[Batch] = {
    // Technically some of the rules in Finish Analysis are not optimizer rules and belong more
    // in the analyzer, because they are needed for correctness (e.g. ComputeCurrentTime).
    // However, because we also use the analyzer to canonicalized queries (for view definition),
    // we do not eliminate subqueries or compute current time in the analyzer.
    Batch("Finish Analysis", Once,
      EliminateSubqueryAliases,
      ReplaceExpressions,
      ComputeCurrentTime,
      GetCurrentDatabase(sessionCatalog),
      RewriteDistinctAggregates) ::
    //////////////////////////////////////////////////////////////////////////////////////////
    // Optimizer rules start here
    //////////////////////////////////////////////////////////////////////////////////////////
    // - Do the first call of CombineUnions before starting the major Optimizer rules,
    //   since it can reduce the number of iteration and the other rules could add/move
    //   extra operators between two adjacent Union operators.
    // - Call CombineUnions again in Batch("Operator Optimizations"),
    //   since the other rules might make two separate Unions operators adjacent.
    Batch("Union", Once,
      CombineUnions) ::
    Batch("Subquery", Once,
      OptimizeSubqueries) ::
    Batch("Replace Operators", fixedPoint,
      ReplaceIntersectWithSemiJoin,
      ReplaceExceptWithAntiJoin,
      ReplaceDistinctWithAggregate) ::
    Batch("Aggregate", fixedPoint,
      RemoveLiteralFromGroupExpressions,
      RemoveRepetitionFromGroupExpressions) ::
    Batch("Operator Optimizations", fixedPoint,
      // Operator push down
      PushProjectionThroughUnion,
      ReorderJoin,
      EliminateOuterJoin,
      PushPredicateThroughJoin, //谓词下推之一
      PushDownPredicate, //谓词下推之一
      LimitPushDown,
      ColumnPruning, //列值剪裁,常用于聚合操作,join左右孩子操作,合并相邻project列
      InferFiltersFromConstraints,
      // Operator combine
      CollapseRepartition,
      CollapseProject,
      CollapseWindow,
      CombineFilters, //谓词下推之一,合并两个相邻的Filter。合并2个节点,就可以减少树的深度从而减少重复执行过滤的代价
      CombineLimits, //合并Limits
      CombineUnions,
      // Constant folding and strength reduction
      NullPropagation,
      FoldablePropagation,
      OptimizeIn(conf),
      ConstantFolding, //常量累加之一
      ReorderAssociativeOperator,
      LikeSimplification,
      BooleanSimplification, //常量累加之一,布尔表达式的提前短路
      SimplifyConditionals,
      RemoveDispensableExpressions,
      SimplifyBinaryComparison,
      PruneFilters,
      EliminateSorts,
      SimplifyCasts,
      SimplifyCaseConversionExpressions,
      RewriteCorrelatedScalarSubquery,
      EliminateSerialization,
      RemoveRedundantAliases,
      RemoveRedundantProject) ::
    Batch("Check Cartesian Products", Once,
      CheckCartesianProducts(conf)) ::
    Batch("Decimal Optimizations", fixedPoint,
      DecimalAggregates) ::
    Batch("Typed Filter Optimization", fixedPoint,
      CombineTypedFilters) ::
    Batch("LocalRelation", fixedPoint,
      ConvertToLocalRelation,
      PropagateEmptyRelation) ::
    Batch("OptimizeCodegen", Once,
      OptimizeCodegen(conf)) ::
    Batch("RewriteSubquery", Once,
      RewritePredicateSubquery,
      CollapseProject) :: Nil
  }

SELECT * FROM