【Spark源码分析】规则框架-`optimization`阶段使用的规则

时间:2024-12-02 07:09:05
Finish Analysis Once EliminateResolvedHint 替换计划中的ResolvedHint算子。将HintInfo移动到关联的Join算子,否则,如果没有匹配的Join算子,就将其删除。
EliminateSubqueryAliases 从计划中删除 SubqueryAlias 操作符。子查询只需要为属性提供范围信息,分析完成后即可删除。
EliminateView 此规则将视图操作符从计划中删除。该操作符在分析阶段结束前一直有效,因为我们希望查看分析逻辑计划的哪一部分是由视图生成的。
ReplaceExpressions 查找所有无价值的 RuntimeReplaceable 表达式,并将其替换为可评估的语义等价表达式。
这主要用于提供与其他数据库的兼容性。举几个例子:我们用它来支持 “left”,将其替换为 “substring”。我们用它来将 Every 和 Any 分别替换为 Min 和 Max。
RewriteNonCorrelatedExists 将非相关存在子查询改写为使用 ScalarSubquery WHERE EXISTS (SELECT A FROM TABLE B WHERE COL1 > 10) 将改写为 WHERE (SELECT 1 FROM (SELECT A FROM TABLE B WHERE COL1 > 10) LIMIT 1) IS NOT NULL
PullOutGroupingExpressions 该规则可确保聚合节点在优化阶段不包含复杂的分组表达式。
复杂的分组表达式被拉出到 “聚合”(Aggregate)下的 “项目”(Project)节点,并在分组表达式和不含聚合函数的聚合表达式中被引用。这些引用可确保优化规则不会将聚合表达式更改为不再引用任何分组表达式的无效表达式,还可简化节点上的表达式转换(只需转换一次表达式)。
ComputeCurrentTime 计算当前日期和时间,确保在一次查询中返回相同的结果。
ReplaceCurrentLike 用当前数据库名称替换 CurrentDatabase 表达式。
用当前目录名称替换 CurrentCatalog 的表达式。
SpecialDatetimeValues 如果输入字符串是可折叠的,则用其date/ timestamp值替换特殊日期时间字符串。
RewriteAsOfJoin 使用 Join 和 Aggregate 运算符的组合替换逻辑 AsOfJoin 运算符。
Eliminate Distinct Once EliminateDistinct 删除无用的 DISTINCT:
对于某些集合表达式,例如 最大值和最小值。2. 如果子代保证了不同语义。
此规则应在 RewriteDistinctAggregates 之前应用。
Inline CTE Once InlineCTE 如果满足条件之一,则将 CTE 定义内联到相应的引用中: 1. CTE 定义不包含任何非确定表达式或包含对外部查询的属性引用。如果此 CTE 定义引用了另一个具有非确定表达式的 CTE 定义,则仍可内联当前 CTE 定义。2. 在整个主查询和所有子查询中,CTE 定义只被引用一次。
出现在子查询中且未内联的 CTE 定义将被上拉到主查询级别。
Union fixedPoint RemoveNoopOperators 从查询计划中删除不做任何修改的禁用操作符。
CombineUnions 将所有相邻的联合运算符合并为一个联合运算符。
RemoveNoopUnion Smplify Union 的子节点,或从查询计划中删除不对查询做任何修改的 no-op Union。
LocalRelation early fixedPoint ConvertToLocalRelation 将 LocalRelation 上的本地操作(即不需要交换数据的操作)转换为另一个 LocalRelation。
PropagateEmptyRelation 该规则在普通优化器中运行, 简化了空或非空关系的查询计划。
UpdateAttributeNullability 通过使用子输出属性(Attributes)中相应属性的无效性,更新已解析逻辑计划(LogicalPlan)中属性的无效性。之所以需要这一步骤,是因为用户可以在数据集 API 中使用已解析的 AttributeReference,而外连接可以改变 AttributeReference 的无效性。如果没有这条规则,可空列的可空字段实际上可能会被设置为不可空,从而导致非法优化(如 NULL 传播)和错误答案。

有关这种情况的具体查询,请参见 SPARK-13484 和 SPARK-13801。
Pullup Correlated Expressions Once OptimizeOneRowRelationSubquery 此规则可优化以 OneRowRelation 作为叶节点的子查询。
PullupCorrelatedPredicates 从给定子查询中提取所有(外部)相关谓词。该方法从子查询过滤器中移除相关谓词,并将这些谓词的引用添加到所有中间项目和聚合子句(如果缺少的话)中,以便能够在顶层对谓词进行评估。
TODO:将此规则与 RewritePredicateSubquery 合并。
Subquery OptimizeSubqueries 优化表达式中的所有子查询
Replace Operators fixedPoint RewriteExceptAll 使用联合、聚合和生成操作符的组合取代逻辑 Except 操作符。
RewriteIntersectAll 使用 Union、Aggregate 和 Generate 运算符的组合取代逻辑 Intersect 运算符。
ReplaceIntersectWithSemiJoin 用左半连接运算符替换逻辑相交运算符。
ReplaceExceptWithFilter 如果逻辑 Except 运算符中的一个或两个数据集使用筛选器进行了纯粹的转换,该规则将通过翻转右侧子数据集的筛选条件,用筛选器运算符替换逻辑 Except 运算符。
ReplaceExceptWithAntiJoin 用左反连接运算符替换逻辑 Except 运算符。
ReplaceDistinctWithAggregate 用聚合运算符替换逻辑去重运算符。
Aggregate fixedPoint RemoveLiteralFromGroupExpressions 删除 Aggregate 中分组表达式中的字面表达式,因为它们对结果没有影响,只会使分组键变大。
RemoveRepetitionFromGroupExpressions 删除聚合中分组表达式的重复,因为它们对结果没有影响,只会使分组键变大。
操作优化规则批operatorOptimizationBatch
Clean Up Temporary CTE Info Once CleanUpTempCTEInfo 清理 CTERelationDef 节点的临时信息。该规则应在 PushdownPredicatesAndPruneColumnsForCTEDef 的所有迭代完成后调用。
Pre CBO Rules Once preCBORules
Early Filter and Projection Push-Down Once earlyScanPushDownRules
Update CTE Relation Stats Once UpdateCTERelationStats 更新CTE应用状态
Join Reorder FixedPoint(1) CostBasedJoinReorder 基于成本的连接重排。未来我们可能会有多种连接重排序算法。该类是这些算法的入口,并选择使用哪种算法。
Eliminate Sorts Once EliminateSorts 如果不影响最终输出排序,则删除排序操作。
Decimal Optimizations fixedPoint DecimalAggregates 通过在未缩放的 Long 值上执行,加快固定精度小数的聚合速度。
Distinct Aggregate Rewrite Once RewriteDistinctAggregates 该规则将具有不同聚合的聚合查询改写为扩展的双重聚合,其中常规聚合表达式和每个不同子句都在单独的组中聚合。然后在第二个聚合中合并结果。
Object Expressions Optimization fixedPoint EliminateMapObjects 满足以下条件时删除MapObject
1. Mapobject(… lambdavariable(…, false) …),这意味着输入和输出类型都是非空的原始类型。

没有指定数据项的自定义集合类表示。
CombineTypedFilters 将两个相邻的 TypedFilters(在条件中对同一类型对象执行操作)合并为一个,将过滤器函数合并为一个连接函数。
ObjectSerializerPruning 从查询计划中删除不必要的对象序列化器。该规则可删除单个序列化器和序列化器中的嵌套字段。
ReassignLambdaVariableID 将每个查询的唯一 ID 重新分配给 LambdaVariables,其原始 ID 是全局唯一的。这有助于 Spark 更频繁地访问 codegen 缓存并提高性能。
LocalRelation fixedPoint ConvertToLocalRelation 将 LocalRelation 上的本地操作(即不需要交换数据的操作)转换为另一个 LocalRelation。
PropagateEmptyRelation 该规则在普通优化器中运行, 简化了空或非空关系的查询计划。
UpdateAttributeNullability 通过使用子输出属性(Attributes)中相应属性的无效性,更新已解析逻辑计划(LogicalPlan)中属性的无效性。之所以需要这一步骤,是因为用户可以在数据集 API 中使用已解析的 AttributeReference,而外连接可以改变 AttributeReference 的无效性。如果没有这条规则,可空列的可空字段实际上可能会被设置为不可空,从而导致非法优化(如 NULL 传播)和错误答案。

有关这种情况的具体查询,请参见 SPARK-13484 和 SPARK-13801。
Optimize One Row Plan fixedPoint OptimizeOneRowPlan 该规则同时适用于普通优化器和 AQE 优化器。它使用最大行数优化计划:
如果排序子代的最大行数小于或等于 1,则删除排序
如果局部排序的子代每个分区的最大行数小于或等于 1,则删除局部排序
如果聚合子代的最大行数小于或等于 1,且其子代仅分组(包括重写的独特计划),则将聚合转换为项目
如果聚合子代的最大行数小于或等于 1,在所有聚合表达式中将 distinct 设置为 false
Check Cartesian Products Once CheckCartesianProducts
RewriteSubquery Once RewritePredicateSubquery 该规则可将谓词子查询改写为左半连接/反连接。支持以下谓词:a. EXISTS/ NOT EXISTS 将被改写为半连接/反连接,过滤器中未解决的条件将被提取出来作为连接条件。b. IN/ NOT IN 将被改写为半连接/反连接,过滤器中未解决的条件将被提取出来作为连接条件,值 = 所选列也将用作连接条件。
PushPredicateThroughJoin 下推筛选运算符,其中的条件只能使用连接左侧或右侧的属性进行评估。其他筛选条件被移到连接条件中。
同时下推连接筛选器,在适用情况下,只需使用子查询左侧或右侧的属性即可对条件进行评估。
LimitPushDown 下推UNION ALLJOIN下的LocalLimit
ColumnPruning 试图消除从查询计划中读取不需要的列。
CollapseProject 将所有相邻的union运算符合并为一个union运算符。
RemoveRedundantAliases 从查询计划中删除冗余别名。冗余别名是指不更改列名或元数据,也不重复列的别名。
RemoveNoopOperators 从查询计划中删除不做任何修改的禁用操作符。
NormalizeFloatingNumbers Once NormalizeFloatingNumbers
ReplaceUpdateFieldsExpression Once ReplaceUpdateFieldsExpression 用an evaluable expression替换 UpdateFields 表达式。