【Spark源码分析】规则框架-草稿
规则批:规则集合序列,由名称、执行策略、规则列表组成。一个规则批里使用一个执行规则。
执行策略
- FixedPoint
- Once
规则:
analysis
分析阶段使用的规则
规则批 | 策略 | 规则 | 说明 |
---|---|---|---|
Substitution | fixedPoint | OptimizeUpdateFields | 该规则优化了 UpdateFields 表达式链,因此看起来更像优化规则。但是,在处理深嵌套模式时,UpdateFields 表达式树可能会非常复杂,导致分析无法进行。因此,我们需要在分析开始时尽早优化 UpdateFields 。 |
CTESubstitution | 分析 WITH 节点,并根据以下条件用 CTE 引用或 CTE 定义替代子计划: 1. 如果在传统模式下,或如果查询是 SQL 命令或 DML 语句,则用 CTE 定义(即内联 CTE)替换。 2. 否则,替换为 CTE 引用 CTERelationRefs。是否内联将在查询分析后由 InlineCTE 规则决定。 替换后未内联的所有 CTE 定义将归入主查询和子查询的一个 WithCTE 节点下。任何不包含 CTE 或已内联所有 CTE 的主查询或子查询显然都不会有任何 WithCTE 节点。如果有,WithCTE 节点将与最外层的 With 节点位于同一位置。 WithCTE 节点中的 CTE 定义将按照它们被解析的顺序排列。这意味着对于任何有效的 CTE 查询,CTE 定义都能保证按照它们的依赖关系以拓扑顺序排列(即,给定 CTE 定义 A 和 B,且 B 引用 A,则 A 保证出现在 B 之前)。否则,这一定是一个无效的用户查询,稍后关系解析规则将抛出分析异常。 | ||
BindParameters | 查找 ParameterizedQuery 中所有已命名的参数,并用用户指定参数中的字面量替换它们。 | ||
WindowsSubstitution | 用 WindowSpecDefinitions 代替子计划。 WindowSpecDefinition 是窗口函数的规范。 | ||
EliminateUnions | 如果只有一个子项,则从计划中删除 Union 算子 | ||
SubstituteUnresolvedOrdinals | 用 UnresolvedOrdinal 表达式替换 “order by ”或 “group by ”中的序号。 | ||
Disable Hints | Once | DisableHints | 当设置了 spark.sql.optimizer.disableHints 时,删除所有提示。这将在分析器开始时执行,以禁用提示功能。 |
Hints | fixedPoint | ResolveJoinStrategyHints | 允许的连接策略提示列表在 JoinStrategyHint.strategies 中定义,连接策略提示可以指定关系别名序列,例如 “MERGE(a, c)”、“BROADCAST(a)”。连接策略提示计划节点将被插入任何与指定名称相匹配的关系(没有不同的别名)、子查询或公共表表达式的顶部。 提示解析的工作方式是向下递归遍历查询计划,找到与指定关系别名之一匹配的关系或子查询。遍历不会超出任何视图引用、子查询别名。 该规则必须在普通表表达式之前执行。 |
ResolveCoalesceHints | COALESCE Hint 提示接受名称 “COALESCE”、“REPARTITION ”和 “REPARTITION_BY_RANGE”。 | ||
Simple Sanity Check | Once | LookupFunctions | 检查 UnresolvedFunction 引用的函数标识符是否在函数注册表中定义。请注意,该规则不会尝试解析 UnresolvedFunction。它只是根据函数标识符执行简单的存在性检查,以快速识别未定义的函数,而不会触发关系解析,这在某些情况下可能会导致昂贵的分区/模式发现过程。为了避免重复查找外部函数,外部函数标识符将存储在本地哈希集 externalFunctionNameSet 中。 |
Keep Legacy Outputs | Once | KeepLegacyOutputs | spark.sql.legacy.keepCommandOutputSchema 为true时,保留 SQL 命令传统输出的规则。ShowTables,ShowNamespaces,DescribeNamespace,ShowTableProperties。 |
Resolution | fixedPoint | ResolveCatalogs | 解析table/view/function/namespace的名称部分目录。 |
ResolveUserSpecifiedColumns | 解析用户指定的列。当用户在 INSERT INTO 中指定列列表时,为 DSv1 提供了重新排列列顺序的特殊规则。DSv2 由 Analyzer.ResolveInsertInto 单独处理。ResolveInsertInto 单独处理。 | ||
ResolveInsertInto | 解析INSERT INTO 语句 | ||
ResolveRelations | 用catalog中的具体关系替换未解决的关系(表和视图)。 | ||
ResolvePartitionSpec | 在分区相关命令中将UnresolvedPartitionSpec 解析成ResolvedPartitionSpec 。 | ||
ResolveFieldNameAndPosition | 根据命令的大小写敏感性解析、规范化和重写字段名称的规则。 | ||
AddMetadataColumns | 当节点缺少已解析的属性时,为子关系的输出添加元数据列。 元数据列的引用是使用 LogicalPlan.metadataOutput 中的列来解析的,但在关系被替换之前,关系的输出不包括元数据列。除非此规则将元数据添加到关系的输出中,否则分析器会检测到没有产生这些列。 只有当节点已解析但缺少其子节点的输入时,该规则才会添加元数据列。这样可以确保除非使用了元数据列,否则不会将其添加到计划中。通过只检查已解析的节点,可确保 * 扩展已完成,这样元数据列就不会被 * 意外选中。此规则会向下解析操作符,以避免过早投影出元数据列。 | ||
DeduplicateRelations | LogicalPlan的关系去重 | ||
ResolveReferences | 解析查询计划中的列引用。基本上,它会自下而上地转换查询计划树,只有当一个计划节点的所有子节点都已解析,且子节点之间不存在冲突属性时,才会尝试解析该节点的引用(详见 hasConflictingAttrs)。 | ||
ResolveLateralColumnAliasReference | 该规则是解决横向列别名的第二阶段。 解析横向列别名,它引用了之前在 SELECT 列表中定义的别名。从计划角度看,它处理两种类型的操作符: 项目和聚合。- 在 “项目 ”中,将引用的横向别名下推到新创建的 “项目 ”中,解析引用这些别名的属性 - 在 “聚合 ”中,在上面插入 “项目 ”节点,并返回到 “项目 ”的解析。 | ||
ResolveExpressionsWithNamePlaceholders | 如果表达式中包含 NamePlaceholders,则解析表达式。NamePlaceholders代表的是占位符的 | ||
ResolveDeserializer | 用已解析为给定输入属性的反序列化表达式替换 UnresolvedDeserializer。 | ||
ResolveNewInstance | 如果正在构造的对象是一个内部类,则通过查找并添加外部作用域来解决 NewInstance 问题。 | ||
ResolveUpCast | 用 Cast 替换 UpCast 表达式,并在可能截断的情况下抛出异常。 | ||
ResolveGroupingAnalytics | 解析grouping函数 | ||
ResolvePivot | 解析Pivot, | ||
ResolveUnpivot | 解析Unpivot, | ||
ResolveOrdinalInOrderByAndGroupBy | 在SQL的许多方言中,在order/sort by和group by子句中使用的顺序位置是有效的。此规则用于将序号位置转换为选择列表中的相应表达式。Spark 2.0中引入了这种支持。如果排序引用或分组依据表达式不是整数而是可折叠表达式,请忽略它们。当spark.sql.orderByOrdinal/spark.sql.groupByOrdinal设置为false,也忽略位置号。 | ||
ExtractGenerator | 从Project操作符的Project列表中提取Generator,并在Project下创建Generator操作符。 在以下情况下,该规则会抛出 AnalysisException: 1. 生成器嵌套在表达式中,例如:SELECT explode(list) + 1 FROM tbl 2. 在项目列表中发现多个生成器,例如:SELECT explode(list), explode(list) FROM tbl 3. 在非 Project 或 Generate 的其他操作符中发现 Generator,例如 SELECT * FROM tbl SORT BY explode(list) | ||
ResolveGenerate | 重写表。生成表达式,这些表达式需要以下一项或多项才能解析:输出的具体属性引用。 从SELECT子句(即从Project)重新定位到Generate子句中。 输出Attribute 的名称是从封装Generator 的Alias 或MultiAlias 表达式中提取的。 | ||
ResolveFunctions | 用具体的 LogicalPlans 代替 UnresolvedFunctionNames。 用具体的表达式替换 UnresolvedFunctions。 用具体表达式替换 UnresolvedGenerators。 用具体的 LogicalPlans 代替 UnresolvedTableValuedFunctions。 | ||
ResolveAliases | 用具体的别名代替 UnresolvedAliass。 | ||
ResolveSubquery | 该规则可解析和重写表达式内部的子查询。 注:CTE 在 CTESubstitution 中处理。 | ||
ResolveSubqueryColumnAliases | 用投影替换子查询中未解决的列别名。 | ||
ResolveWindowOrder | 检查和添加顺序到AggregateWindowFunction | ||
ResolveWindowFrame | 检查并为所有窗口功能添加合适的窗口框架。 | ||
ResolveNaturalAndUsingJoin | 根据两侧的输出计算输出列,消除自然连接或使用连接,然后在普通连接上应用 Project 消除自然连接或使用连接。 | ||
ResolveOutputRelation | 根据逻辑计划中的数据解析输出表的列。该规则将 - 按名称写入时重新排列列顺序 - 在数据类型不匹配时插入转换 - 在列名不匹配时插入别名 - 检测与输出表不兼容的计划并抛出 AnalysisException | ||
ExtractWindowExpressions | 从 Project 运算符的 projectList 和 Aggregate 运算符的 aggregateExpressions 中提取 WindowExpressions,并为每个不同的 WindowSpecDefinition 创建单独的 Window 运算符。 | ||
GlobalAggregates | 将包含聚合表达式的投影转化为聚合。 | ||
ResolveAggregateFunctions | 该规则可查找不在聚合运算符中的聚合表达式。例如,HAVING 子句或 ORDER BY 子句中的表达式。这些表达式会被下推到底层的聚合运算符,然后在原始运算符后被投影掉。 在从中查找聚合函数和分组表达式之前,我们需要确保所有表达式都已完全解析。 | ||
TimeWindowing | 使用扩展运算符将时间列映射到多个时间窗口。要知道一个时间列可以映射到多少个窗口并非易事,因此我们会高估窗口的数量,并过滤掉时间列不在时间窗口内的行。 | ||
SessionWindowing | 将时间列映射到会话窗口。 | ||
ResolveWindowTime | 解析 window_time 表达式,从作为窗口聚合运算符输出的窗口列中提取正确的窗口时间。窗口列的类型为 struct { start: TimestampType, end: TimestampType }。窗口的正确代表事件时间是 window. | ||
ResolveDefaultColumns | 这是一条在 CREATE/ REPLACE TABLE 等语句中处理 DEFAULT 列的规则。 CREATE TABLE 和 ALTER TABLE 调用支持为以后的操作设置列默认值。随后的 INSERT、UPDATE 和 MERGE 命令可根据需要使用 DEFAULT 关键字引用该值。 | ||
ResolveInlineTables | 使用LocalRelation 替换UnresolvedInlineTable | ||
ResolveLambdaVariables | 解决高阶函数公开的 lambda 变量。 该规则分两步运行: [1]. 将高阶函数公开的匿名变量绑定到 lambda 函数的参数上;这样就创建了命名和类型化的 lambda 变量。在这一步中,将检查参数名称是否重复,并检查参数的数量。 [2]. 解析 lambda 函数的函数表达式树中使用的 lambda 变量。请注意,我们允许使用当前 lambda 之外的变量,这些变量可以是定义在外层作用域中的 lambda 函数,也可以是由计划的子计划产生的属性。如果名称重复,则使用最内部作用域中定义的名称。 | ||
ResolveTimeZone | 用会话本地时区的副本替换不含时区 ID 的 TimeZoneAwareExpression。 | ||
ResolveRandomSeed | 设置随机数生成的种子。 | ||
ResolveBinaryArithmetic | 解析二进制算法 对于加法 1. 如果两边都是时间间隔,则保持不变; 2. 否则,如果一边是日期,另一边是时间间隔,则将其转为 DateAddInterval; 3. 否则,如果一边是时间间隔,则将其转为 TimeAdd; 4. 否则,如果一边是日期,则将其转为 DateAdd; 5. 否则保持不变。 减法 1. 如果两边都是时间间隔,则保持不变; 2. 否则,如果左边是日期,右边是区间,则将其转为(l, -r); 3. 否则,如果右边是区间,则将其转为(l, -r); 4. 否则,如果一边是时间戳,则将其转为 SubtractTimestamps; 5. 否则,如果右边是日期,则将其转为 DateDiff/SubtractDates; 6. 否则,如果左边是日期,则将其转为 DateSub; 7. 否则改为保持不变。 乘法 1. 如果一边是区间,则将其转换为 MultiplyInterval; 2. 否则保持不变。 对于除法 1. 如果左边是区间,则将其转为 DivideInterval; 2. 否则,保持不变。 | ||
ResolveUnion | 将 Union 的不同子代解析为一组共同的列。 | ||
RewriteDeleteFromTable | 重写 DELETE 操作的规则,使用对单行或行群组进行操作的计划。 如果表实现了 SupportsDeleteV2 和 SupportsRowLevelOperations,该规则仍将重写 DELETE 操作,但优化器会检查是否可以通过向连接器传递删除筛选器来处理该特定 DELETE 语句。如果可以,优化器将放弃重写的计划,并允许数据源使用过滤器删除。 | ||
typeCoercionRules | 当spark.sql.ansi.enabled 设置为 true 的时候,采取 ANSI 的方式进行解析,这代表的是一组解析规则。 | ||
ResolveWithCTE | 使用相应 CTE 定义的解析输出属性更新 CTE 引用。 | ||
Remove TempResolvedColumn | Once | RemoveTempResolvedColumn | 主解析批次中的 ResolveReferences 规则会在 UnresolvedHaving/ Filter/ Sort 中创建 TempResolvedColumn,用于保存临时解析的带有 agg. 如果托管 TempResolvedColumn 的表达式已完全解析,则规则 ResolveAggregationFunctions 将 - 如果 TempResolvedColumn 位于聚合函数或分组表达式中,则用 AttributeReference 替换 TempResolvedColumn。- 如果 TempResolvedColumn 不在聚合函数或分组表达式中,则将其标记为已尝试,希望其他规则能重新解决它。如果 hasTried 为真,ResolveReferences 将重新解析 TempResolvedColumn,如果解析失败,则保持不变。我们应该将其转回 UnresolvedAttribute,这样分析器稍后就能报告缺少列的错误。 如果托管 TempResolvedColumn 的表达式未被解析,TempResolvedColumn 将保持 hasTried 为 false。我们应该剥离 TempResolvedColumn,这样用户就能看到表达式未解析的原因,例如类型不匹配。 |
Post-Hoc Resolution | Once | ResolveCommandsWithIfExists | 用于在未解析表或临时视图时处理命令的规则。这些命令支持 “ifExists ”标志,因此在未解析关系时不会失败。如果 “ifExists ”标志被设为 true,则该计划将被解析为 NoopCommand. |
Remove Unresolved Hints | Once | RemoveAllHints | 删除所有hits,用于删除用户提供的无效hits。必须在执行完所有其他hits规则后才能执行。 |
Nondeterministic | Once | PullOutNondeterministic | 从非 Project 或过滤器的 LogicalPlan 中提取非确定表达式,将其放入内部 Project,最后将其投射到外部 Project。 |
UDF | Once | HandleNullInputsForUDF | 通过添加额外的 If 表达式来进行空值检查,从而正确处理 UDF 的空基元输入。当用户使用基元参数定义 UDF 时,无法判断基元参数是否为空,因此我们假定基元输入为可传递的空,如果输入为空,则返回空。 |
ResolveEncodersInUDF | 通过明确给出属性来解决 UDF 的编码器问题。我们明确给出属性是为了处理输入值的数据类型与编码器内部模式不一致的情况,这可能会导致数据丢失。例如,如果实际数据类型是 Decimal(30,0),编码器不应将输入值转换为 Decimal(38,18)。 解析后的编码器将用于将内部行反序列化为 Scala 值。 | ||
UpdateNullability | Once | UpdateAttributeNullability | 通过使用子输出属性(Attributes)中相应属性的无效性,更新已解析逻辑计划(LogicalPlan)中属性的无效性。之所以需要这一步骤,是因为用户可以在数据集 API 中使用已解析的 AttributeReference,而外连接可以改变 AttributeReference 的无效性。如果没有这条规则,可空列的可空字段实际上可能会被设置为不可空,从而导致非法优化(如 NULL 传播)和错误答案。 有关这种情况的具体查询,请参见 SPARK-13484 和 SPARK-13801。 |
Subquery | Once | UpdateOuterReferences | 引用外部查询块的子查询中的聚合表达式会被推送到外部查询块进行评估。下面的规则更新了此类外部引用,如 AttributeReference 引用父查询块/外部查询块中的属性。 |
Cleanup | fixedPoint | CleanupAliases | 清除计划中不必要的别名。基本上,我们只需要在 Project(项目列表)或 Aggregate(聚合表达式)或 Window(窗口表达式)中将别名作为顶层表达式。请注意,如果一个表达式有其他不在其子表达式中的表达式参数,如 RuntimeReplaceable,则本规则中的别名转换对这些参数不起作用。 |
HandleSpecialCommand | Once | HandleSpecialCommand | 用于处理分析完成后需要通知的特殊命令的规则。该规则应在所有其他分析规则运行后运行。 |
Remove watermark for batch query | Once | EliminateEventTimeWatermark | 忽略批量查询中的事件时间水印,该功能仅在结构化数据流中支持。TODO:将此规则添加到分析器规则列表中。 |
optimization
阶段使用的规则
操作优化的规则批 operatorOptimizationBatch
- 算子下推
- 算子合并
- 常量折叠和强度消减
- 过滤推断
- 过滤推断后的算子优化
- 下推join的额外谓词
规则批 | 策略 | 规则 | 说明 |
---|---|---|---|
Operator Optimization before Inferring Filters | fixedPoint | PushProjectionThroughUnion | 将Project操作符推送到Union操作符的两侧。可安全下推的操作如下所示。Union:现在,Union就意味着Union ALL,它不消除重复行。因此,通过它下推Filter和Project是安全的。下推Filter是由另一个规则PushDownPredicates处理的。一旦我们添加了UNION DISTINCT,我们就无法下推Project了。 |
PushProjectionThroughLimit | 将Project操作符下推到Limit操作符。 | ||
ReorderJoin | 重新排列连接的顺序,将所有条件推入Join,使最下面的连接至少有一个条件。 如果所有连接都至少有一个条件,则连接顺序不会改变。 如果启用了星形模式检测,则会根据启发式方法对星形连接计划重新排序。 | ||
EliminateOuterJoin | 1. 如果谓词可以限制结果集,从而消除所有空行,则消除外部连接 2. 如果聚合来自流式侧且不考虑重复,则移除外部连接 3. 删除外连接 对于只选择左侧列的左外部连接,且右侧连接键是唯一的。 对于右外部连接,只选择右侧列,且左侧连接键是唯一的。 该规则应在下推 “过滤器 ”之前执行 | ||
PushDownPredicates | 普通操作符和连接的谓词下推统一版本。该规则提高了级联Join(如:过滤-连接-连接-连接)的谓词下推性能: Filter-Join-Join-Join。大多数谓词可以一次性下推。 | ||
PushDownLeftSemiAntiJoin | 该规则是 PushPredicateThroughNonJoin 的变体,可以处理以下操作符下面的左半连接和左反连接。1) 项目 2) 窗口 3) 联合 4) 聚合 5) 其他允许的一元操作符。请参阅 PushPredicateThroughNonJoin。 | ||
PushLeftSemiLeftAntiThroughJoin | 该规则是 PushPredicateThroughJoin 的变体,可以处理连接操作符下面的左半连接和左反连接。允许的连接类型有 1) 内连接 2) 交叉连接 3) 左外连接 4) 右外连接 | ||
LimitPushDown | 下推UNION ALL 和JOIN 下的LocalLimit 。 | ||
LimitPushDownThroughWindow | 下推Window 下方的LocalLimit 。 | ||
ColumnPruning | 试图消除从查询计划中读取不需要的列。 | ||
GenerateOptimization | 如果生成的project不引用任何生成的属性(例如,对已爆炸数组进行类似计数的聚合),则从生成中删除不必要的字段。 | ||
CollapseRepartition | 合并相邻的RepartitionOperation 和RebalancePartitions 运算符 | ||
CollapseProject | 将所有相邻的union运算符合并为一个union运算符。 | ||
OptimizeWindowFunctions | 将 first(col) 替换为 nth_value(col,1),以提高性能。 | ||
CollapseWindow | 折叠相邻窗口表达式。 如果分区规格和顺序规格相同,窗口表达式独立且窗口函数类型相同,则折叠到父窗口。 | ||
CombineFilters | 将两个相邻的过滤运算符合并为一个,将非冗余条件合并为一个连接谓词。 | ||
EliminateOffsets | 该规则通过以下方式优化偏移运算符 1. 如果偏移 == 0,则取消偏移运算符。 2. 如果 Offset 的子代 max row = offset,则将 Offset 运算符替换为空 LocalRelation。 3. 将两个相邻的 Offset 操作符合并为一个,将表达式合并为一个表达式。 | ||
EliminateLimits | 普通优化器和 AQE 优化器都采用这一规则,并通过以下方式优化极限运算符: 1. 如果子行 max 行 = limit,则消除 Limit/GlobalLimit 运算符。 2. 如果极限值为零 (0),则用空的 LocalRelation 替换 Limit/LocalLimit/GlobalLimit 运算符。 3. 将两个相邻的 Limit 操作符合并为一个,将表达式合并为一个表达式。 | ||
CombineUnions | 将所有相邻的联合运算符合并为一个联合运算符。 | ||
OptimizeRepartition | 如果所有分区表达式都是可折叠的,且用户未指定,则将 RepartitionByExpression numPartitions 替换为 1。 | ||
TransposeWindow | 转置相邻窗口表达式。 如果父窗口表达式的分区规范与子窗口表达式的分区规范兼容,则将它们换位。 | ||
NullPropagation | 用等效的字面值替换可静态求值的表达式。该规则与表达式树中从下到上传播空值的规则更为相似。 | ||
NullDownPropagation | 如果输入不允许为空,则展开IsNull/IsNotNull 的输入,例如:IsNull(Not(null)) == IsNull(null) | ||
ConstantPropagation | 用连接表达式中的相应值替换可以静态计算的属性 | ||
FoldablePropagation | 如果可能,用原始可折叠表达式的别名替换属性。其他优化将利用传播的可折叠表达式。 | ||
OptimizeIn | 优化 IN 谓词: 1. 当列表为空且值不可为空时,将谓词转换为 false。 2. 删除字面重复。 3. 用优化版本(value、HashSet[Literal])取代(value、seq[Literal]),后者速度更快 | ||
OptimizeRand | Rand() 生成的随机列的 i. i. d. 值在 [0, 1) 范围内均匀分布,因此在二进制比较中,用 1.0 或 0.0 比较 double literal 值可以消除 Rand()。 | ||
ConstantFolding | 用等价的字面值替换可静态评估的表达式。 | ||
EliminateAggregateFilter | 删除聚合表达式中无用的 FILTER 子句。此规则应在 RewriteDistinctAggregates 之前应用。 | ||
ReorderAssociativeOperator | 对关联积分型运算符重新排序,并将所有常量合二为一。 | ||
LikeSimplification | 简化不需要完整正则表达式来计算条件的LIKE表达式。 | ||
BooleanSimplification | 简化布尔表达式 1. 简化无需对两边求值即可确定答案的表达式。 2. 消除/提取公因式 3. 合并相同的表达式 4. 删除不运算符 | ||
SimplifyConditionals | 简化条件表达式(if/case)。 | ||
PushFoldableIntoBranches | 将可折叠表达式推入(if/case)分支。 | ||
RemoveDispensableExpressions | 删除不需要的节点 | ||
SimplifyBinaryComparison | 使用语义相等的表达式简化二进制比较: 1.用 true 文本值替代<==> ;2.如果操作数都是非空的,用 true 文本值替代 = , <= , 和 >= ;3.如果操作数都是非空的,用 false 文本值替代> 和< ;4.如果有一边操作数是布尔文本值,就展开 = 、<=> | ||
ReplaceNullWithFalseInPredicate | |||
PruneFilters | 移除可以简单评估的过滤器。具体方法如下 1) 在过滤器总是求值为真的情况下,删除过滤器。 2) 当过滤器的结果总是为假时,用一个空关系来代替。 3) 根据子代输出的限制条件,消除总是为真的条件。 | ||
SimplifyCasts | 移除因输入已是正确类型而不必要的 Cast。 | ||
SimplifyCaseConversionExpressions | 删除不必要的内部大小写转换表达式,因为内部转换已被外部转换覆盖。 | ||
RewriteCorrelatedScalarSubquery | 该规则将相关的 ScalarSubquery 表达式重写为 LEFT OUTER 连接。 | ||
RewriteLateralSubquery | 该规则将 LateralSubquery 表达式改写为连接。 | ||
EliminateSerialization | 删除不必要地在数据项的对象和序列化(InternalRow)表示之间切换的情况。 | ||
RemoveRedundantAliases | 从查询计划中删除冗余别名。冗余别名是指不更改列名或元数据,也不重复列的别名。 | ||
RemoveRedundantAggregates | 从查询计划中删除冗余聚合。冗余聚合是一种聚合,其唯一目标是保留不同的值,而其父聚合会忽略重复的值。 | ||
UnwrapCastInBinaryComparison | |||
RemoveNoopOperators | 从查询计划中删除不做任何修改的禁用操作符。 | ||
OptimizeUpdateFields | 优化 UpdateFields 表达链。 | ||
SimplifyExtractValueOps | 简化冗余的 CreateNamedStruct、CreateArray 和 CreateMap 表达式。 | ||
OptimizeCsvJsonExprs | 简化多余的 csv/ json 相关表达式。 | ||
CombineConcats | 合并嵌套的 Concat 表达式 | ||
PushdownPredicatesAndPruneColumnsForCTEDef | 从参考点推断 CTERelationDef 的谓词和列剪枝,并将分词谓词和属性联合向下推入 CTE 计划。 | ||
Infer Filters | Once | InferFiltersFromGenerate | 从Generate中推导出过滤器,从而可以在连接前和数据源中提前删除Generate本应删除的行。 |
InferFiltersFromConstraints | 从操作符的现有约束中生成附加筛选器列表,但要移除那些已经是操作符条件一部分或操作符子约束一部分的筛选器。这些筛选器目前插入到筛选运算符中的现有条件以及连接运算符的两侧。 注意:虽然这种优化适用于很多类型的连接,但它主要有利于内部连接和左半连接。 | ||
Operator Optimization after Inferring Filters | fixedPoint | 同Operator Optimization before Inferring Filters 一样 | |
Push extra predicate through join | fixedPoint | PushExtraPredicateThroughJoin | 尝试将析取连接条件下推到左右子项中。为了避免扩展连接条件,即使发生谓词下推,连接条件也会保持原来的形式。 |
PushDownPredicates | 普通操作符和连接的谓词下推统一版本。该规则提高了级联Join(如:过滤-连接-连接-连接)的谓词下推性能: Filter-Join-Join-Join。大多数谓词可以一次性下推。 |
算子合并
规则批 | 策略 | 规则 | 说明 |
---|---|---|---|
Operator Optimization before Inferring Filters | fixedPoint | PushProjectionThroughUnion | 将Project操作符推送到Union操作符的两侧。可安全下推的操作如下所示。Union:现在,Union就意味着Union ALL,它不消除重复行。因此,通过它下推Filter和Project是安全的。下推Filter是由另一个规则PushDownPredicates处理的。一旦我们添加了UNION DISTINCT,我们就无法下推Project了。 |
Finish Analysis: 对包括所有子查询在内的整个计划应用完成分析规则。
规则批 | 策略 | 规则 | 说明 |
---|---|---|---|
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 ALL 和JOIN 下的LocalLimit 。 | ||
ColumnPruning | 试图消除从查询计划中读取不需要的列。 | ||
CollapseProject | 将所有相邻的union运算符合并为一个union运算符。 | ||
RemoveRedundantAliases | 从查询计划中删除冗余别名。冗余别名是指不更改列名或元数据,也不重复列的别名。 | ||
RemoveNoopOperators | 从查询计划中删除不做任何修改的禁用操作符。 | ||
NormalizeFloatingNumbers | Once | NormalizeFloatingNumbers | |
ReplaceUpdateFieldsExpression | Once | ReplaceUpdateFieldsExpression | 用an evaluable expression替换 UpdateFields 表达式。 |
相关文章:
【Spark源码分析】规则框架-草稿
规则批:规则集合序列,由名称、执行策略、规则列表组成。一个规则批里使用一个执行规则。 执行策略 FixedPointOnce 规则: #mermaid-svg-1cvqR4xkYpMuAs77 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px…...
力扣第 77 题 组合
题目描述 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按任意顺序返回答案。 示例 示例 1 输入: n 4, k 2输出: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]示例 2 输入: n 1, k …...
postman中获取随机数、唯一ID、时间日期(包括当前日期增减)截取指定位数的字符等
在Postman中,您可以使用内置的动态变量和编写脚本的方式来获取随机数、唯一ID、时间日期以及截取指定位数的字符。以下是具体的操作方法: 一、postman中获取随机数、唯一ID、时间日期(包括当前日期增减)截取指定位数的字符等 获取…...
【汇编】逻辑指令
文章目录 一、逻辑运算指令(一)各逻辑运算指令格式及操作(1)逻辑非指令 NOT(2)逻辑与指令 AND(3)逻辑或指令 OR(4)异或指令 XOR(5)测试…...
LinkedList的了解
一、LinkedList的定义与类型 Java中的LinkedList类是一个双向链表(Doubly Linked List)。与单向链表(Singly Linked List)不同,双向链表中的每个节点不仅包含指向下一个节点的引用,还包含指向前一个节点的…...
2411mfc,修改按钮颜色
添加消息:ON_WM_CTLCOLOR() //在OnInitDialog()方法中添加{HWND hSatateWnd GetDlgItem(IDC_CHK)->GetSafeHwnd();SetWindowTheme(hSatateWnd, _T(""), _T(""));}头文件中: afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);HBRUSH O…...
NLP中的主题模型:LDA(Latent Dirichlet Allocation, 潜在狄利克雷分配)
探索自然语言处理中的主题模型:LDA与狄利克雷分布 主题模型是一种用于发现文档集合中潜在主题的概率生成模型。其中,LDA(Latent Dirichlet Allocation, 潜在狄利克雷分配)是最著名的主题模型之一。在 LDA 中,狄利克雷…...
javaweb Day11
Maven高级 1.分模块设计...
pnpm的menorepo项目配置eslint和prettier
1、使用eslint脚手架安装相关依赖并生成对应配置文件 pnpm dlx eslint/create-config 自动安装了以下几个插件 生成的配置文件如下所示,和csdn其他教程里面不一样,这是因为eslint升级成9.xx版本了 需要node版本20以上 eslint 9.x 升级或使用指南…...
从0开始linux(38)——线程(1)线程概念
欢迎来到博主专栏:从0开始linux 博主ID:代码小豪 文章目录 进程与线程线程概念线程的优点线程的独立数据 进程与线程 如果要理解线程,那么进程将会时绕不开的点。首先我们回顾一下我们之前在进程章节当中是如何描述进程的? 进程&…...
【Linux系统编程】:进程池(简易版)
目录 1.制作游戏菜单 2.对管道进行描述和组织 3.初始化管道 3.1子进程执行任务slaver() 3.2检查管道是否创建有误 4.父进程向管道写入(控制子进程执行任务) 5.清理资源 修改初始化管道代码 6.完整代码: 1.制作游戏菜单 我们利用管道…...
uniapp实现小程序的版本更新
参考官方文档:uni.getUpdateManager() | uni-app官网 uni.getUpdateManager()是uniapp框架提供的一个API,用于管理小程序的版本更新。这个API返回一个全局唯一的版本更新管理器对象,该对象可以用于检测新版本、下载新版本以及提示用户重启应…...
嵌入式QT学习第4天:Qt 信号与槽
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本章思维导图如下: 不使用 Qt Designer 的方式进行开发,用代码绘界面,可以锻炼我们的布局能力,和代码逻辑能力&#x…...
`asyncio.wait` 和 `asyncio.gather` 的区别
asyncio.wait 和 asyncio.gather 的区别 1. asyncio.wait2. asyncio.gather主要区别总结 在Python的异步编程中,asyncio.wait 和 asyncio.gather 都是用于等待多个异步任务完成的工具,但它们在功能和使用方式上有一些关键的区别。本文将详细解释这两个函…...
【JavaEE】多线程(2)
一、线程安全 1.1 线程安全的概念 线程是随机调度执行的,如果多线程环境下的程序运行的结果符合我们预期则说明线程安全,反之,如果遇到其他结果甚至引起了bug则说明线程不安全 1.2 经典例子与解释 下面举一个经典的线程不安全的例子&…...
虚拟地址空间与物理内存(Linux系统)
个人主页:敲上瘾-CSDN博客 个人专栏:Linux学习、游戏、数据结构、c语言基础、c学习、算法 目录 问题引入 一、什么是虚拟内存 二、虚拟内存的描述与组织 三、页表的优势 四、虚拟内存区域划分 问题引入 为引入今天的话题,我们先来看下面…...
iOS Arkit机器学习相关
最近在搞追踪运动物体,然后Arkit识别3d模型和图片,静止状态还不错,运动时候效果还是有点差,所以搞了下苹果的CoreML,苹果官网也有一些训练好的模型 苹果模型列表,自己参考或者使用,提供一个数据…...
Maven CMD命令
打包测试命令 在当前文件中 >mvn clean package -D maven.test.skiptrue 基本命令 mvn clean 清理目标目录(target)中的输出文件。 mvn compile 编译主源代码路径(src/main/java)下的 Java 代码。 mvn test-compile 编译测试源…...
DM-VIO(ROS)+t265配置运行记录(ubuntu18.04+ros melodic)
在工作中需要对DM-VIO算法进行测试,于是配置并记录了一下: 首先运行ros接口的dm-vio,一定要先配置源码 https://github.com/lukasvst/dm-vio在这个网址把源码下载下来并解压,并安装一下依赖: sudo apt-get install …...
DETR:一种新颖的端到端目标检测与分割框架
DETR:一种新颖的端到端目标检测与分割框架 摘要: 随着深度学习技术的发展,目标检测和图像分割任务取得了显著的进步。然而,传统的基于区域提名的方法在处理这些问题时存在一定的局限性。为此,Facebook AI Research&am…...
Android 输入事件拦截机制
Keyboard产生按键事件后,会通过notifyKey开始传递: frameworks\native\services\inputflinger\InputDispatcher.cpp void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {...uint32_t policyFlags args->policyFlags;//只关注policyFlags…...
【Figma】中文版安装
一、软件安装包下载 打开官网链接https://www.figma.com/downloads/下载相应安装包 或使用我已下载好的链接: FigmaSetup.exe 链接: https://pan.baidu.com/s/113eQ8JRETdeOwUp2B3uieA?pwd4vep 二、安装流程 1.点击安装包 2.选择在浏览器登录 3.输入账号密码&a…...
SolarCube: 高分辨率太阳辐照预测基准数据集
太阳能作为清洁能源在减缓气候变化中的作用日益凸显,其稳定的供应对电网管理至关重要。然而,太阳辐照受云层和天气变化的影响波动较大,给光伏电力的管理带来挑战,尤其是在调度、储能和备用系统管理方面。因此,精确的太…...
arkTS:持久化储存UI状态的基本用法(PersistentStorage)
arkUI:持久化储存UI状态的基本用法(PersistentStorage) 1 主要内容说明2 例子2.1 持久化储存UI状态的基本用法(PersistentStorage)2.1.1 源码1的相关说明2.1.1.1 数据存储2.1.1.2 数据读取2.1.1.3 动态更新2.1.1.4 显示…...
【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏
【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…...
第二部分shell----二、shell 条件测试
一、基本语法 在shell程序中,用户可以使用测试语句来测试指定的条件表达式的条件的真或假。当指定的条件为 真时,整个条件测试的返回值为0;反之,如果指定的条件为假,则条件测试语句的返回值为非0值。 1.test<测试表…...
node修改文件名称
node修改名称 var fs require(fs); const events require(events); var path require(path);init(); function init() {//要遍历的文件夹所在的路径const dirPath path.resolve(__dirname, "data");//遍历目录fileDisplay(dirPath); }/*** 文件遍历* param dirP…...
Vue教程|搭建vue项目|Vue-CLI新版脚手架
一、安装Node环境 安装Node及Npm环境 Node下载地址:Node.js — Run JavaScript EverywhereNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/en/ 安装完成后,检查安装是否成功,并检查版本,命令如下: node -v npm -v mac@Macd…...
Java设计模式
Java设计模式 一、观察者设计模式1.1 概述1.2 结构1.3 特点1. 优点2. 缺点3. 使用场景 1.4 JDK中的实现1. Observable 类2. Observer 接口3. 例子 二、模板设计模式三、单例设计模式一、懒汉式单例二、饿汉式单例 四、Builder模式4.1 概述4.2 结构4.3 具体实现4.4 使用场景 一、…...
java 接口防抖
防抖:防止重复提交 在Web系统中,表单提交是一个非常常见的功能,如果不加控制,容易因为用户的误操作或网络延迟导致同一请求被发送多次,进而生成重复的数据记录。要针对用户的误操作,前端通常会实现按钮的l…...
[C++并发编程] 线程基础
线程发起 最简单的发起一个线程。 void thread_work(std::string str) {std::cout << "str: " << std << std::endl; } //初始化并启动一个线程 std::thread t1(thread, wangzn2016); 线程等待: 线程发起后,可能新的线…...
基于若依框架和Vue2 + Element-UI 实现图片上传组件的重写与优化
背景 在使用 若依分离版Element-UI 的图片上传组件时,需要根据业务需求进行定制化处理,比如: 需要传递额外的业务参数到后端需要对上传路径进行修改需要对上传组件进行样式定制 实现步骤 1. 创建本地组件 首先在业务模块下创建本地的图片上传组件: src/views/xxx/compone…...
自定义类型: 结构体、枚举 、联合
目录 结构体 结构体类型的声明 匿名结构体 结构的自引用 结构体变量的定义和初始化 结构体成员变量的访问 结构体内存对齐 结构体传参 位段 位段类型的声明 位段的内存分配 位段的跨平台问题 位段的应用 枚举 枚举类型的定义 枚举的优点 联合体(共用体) 联合…...
力扣98:验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入…...
Java Stream reduce 函数,聚合数据
Stream.reduce() 是 Stream 的一个聚合方法,它可以把一个 Stream 的所有元素按照自定义聚合逻辑,聚合成一个结果。 先看一个简单数字求和: public class Main {public static void main(String[] args){int sum Stream.of(1, 2…...
npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open
这里写目录标题 报错信息1解决方案 报错信息2解决方案 报错信息1 使用npm install -gvue/cli时,发生报错,报错图片如下: 根据报错信息可以知道,缺少package.json文件。 解决方案 缺什么补什么,这里我们使用命令npm…...
阿里云服务器(centos7.6)部署前后端分离项目(MAC环境)
Jdk17安装部署 下载地址:https://www.oracle.com/java/technologies/downloads/ 选择自己需要的jdk版本进行下载。 通过mac终端scp命令上传下载好的jdk17到服务器的/usr/local目录下 scp -r Downloads/jdk-17.0.13_linux-x64_bin.tar.gz 用户名服务器ip地址:/us…...
【机器学习】机器学习基础
什么是机器学习? 机器学习(Machine Learning, ML)是一种人工智能(AI)的分支,指计算机通过数据学习规律并做出预测或决策,而无需明确编程。它的核心目标是让机器能够从经验中学习,逐…...
BUUCTF—Reverse—Java逆向解密(10)
程序员小张不小心弄丢了加密文件用的秘钥,已知还好小张曾经编写了一个秘钥验证算法,聪明的你能帮小张找到秘钥吗? 注意:得到的 flag 请包上 flag{} 提交 需要用专门的Java反编译软件:jd-gui 下载文件,发现是个class文…...
基于JSP+MySQL的网上招聘系统的设计与实现
摘要 在这样一个经济飞速发展的时代,人们的生存与生活问题已成为当代社会需要关注的一个焦点。对于一个刚刚 踏入社会的年轻人来说,他对就业市场和形势了解的不够详细,同时对自己的职业规划也很模糊,这就导致大量的 时间被花费在…...
js 中 file 文件 应用
文章目录 文件上传File 对象基本属性文件上传大文件上传文件格式校验通过 type 属性校验图片格式通过文件名扩展名校验 文件解析一、处理图片文件流(以 Blob 格式接收文件流为例)二、处理文本文件流三、处理 PDF 文件流(借助 PDF.js 库来展示…...
Java 泛型详细解析
泛型的定义 泛型类的定义 下面定义了一个泛型类 Pair,它有一个泛型参数 T。 public class Pair<T> {private T start;private T end; }实际使用的时候就可以给这个 T 指定任何实际的类型,比如下面所示,就指定了实际类型为 LocalDate…...
「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏
本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字,应用会判断是否接近目标数字,并提供提示“高一点”或“低一点”,直到用户猜中目标数字。这个小游戏结合状态管理和用户交互,是一个入门级的互动应用示例。 关键词 UI互…...
自然语言处理期末试题汇总
建议自己做,写完再来对答案。答案可能存在极小部分错误,不保证一定正确。 一、选择题 1-10、C A D B D B C D A A 11-20、A A A C A B D B B A 21-30、B C C D D A C A C B 31-40、B B B C D A B B A A 41-50、B D B C A B B B B C 51-60、A D D …...
记录Threadlocal使用
编写ThreadLocal工具类 package com.jjking.jplan.context;public class BaseContext<T> {public static final ThreadLocal threadLocal new ThreadLocal();//存储用户public static void set(Object t) {threadLocal.set(t);}//获取用户public static <T> T ge…...
利用 SpringBoot 开发的新冠密接者跟踪系统:医疗机构疫情防控辅助方案
摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古…...
vue 2 父组件根据注册事件,控制相关按钮显隐
目标效果 我不注册事件,那么就不显示相关的按钮 注册了事件,才会显示相关内容 实现思路 组件在 mounted 的时候可以拿到父组件注册监听的方法 拿到这个就可以做事情了 mounted() {console.log(this.$listeners, this.$listeners);this.show.search !…...
【深度学习基础】一篇入门模型评估指标(分类篇)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀深度学习_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. 模…...
hls视频流学习
hls格式播放的依赖安装: <!-- 新增hls播放库 -->npm install hls.js 组件封装: <template><div class"hls-player-cls"><video ref" video" controls style"width: 100%; max-width: 800px;">…...
【electron-vite】搭建electron+vue3框架基础
一、拉取项目 electron-vite 中文文档地址: https://cn-evite.netlify.app/guide/ 官网网址:https://evite.netlify.app/ 版本 vue版本:vue3 构建工具:vite 框架类型:Electron JS语法:TypeScript &…...