当前位置: 首页 > news >正文

【Spark源码分析】规则框架-草稿

规则批:规则集合序列,由名称、执行策略、规则列表组成。一个规则批里使用一个执行规则。

执行策略

  • FixedPoint
  • Once

规则:

RuleExecutor
Analyzer
Substitution
DisableHints
Hints
SimpleSanityCheck
KeepLegacyOutputs
Resolution
RemoveTempResolvedColumn
Post-HocResolution
RemoveUnresolvedHints
Nondeterministic
UDF
UpdateNullability
Subquery
Cleanup
HandleSpecialCommand
RemovewatermarkForBatchQuery
Optimizer
EliminateDistinct
InlineCTE
Union
PullupCorrelatedExpressions
Subquery
ReplaceOperators
Aggregate
CleanUpTemporaryCTEInfo
PreCBORules
EarlyFilterandProjectionPush-Down
UpdateCTERelationStats
JoinReorder
EliminateSorts
DecimalOptimizations
DistinctAggregateRewrite
ObjectExpressionsOptimization
LocalRelation
OptimizeOneRowPlan
CheckCartesianProducts
RewriteSubquery
NormalizeFloatingNumbers
ReplaceUpdateFieldsExpression
OperatorOptimizationBeforeInferringFilters
InferFilters
OperatorOptimizationAfterInferringFilters
PushExtraPredicateThroughjoin

analysis分析阶段使用的规则

规则批策略规则说明
SubstitutionfixedPointOptimizeUpdateFields该规则优化了 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 HintsOnceDisableHints当设置了 spark.sql.optimizer.disableHints 时,删除所有提示。
这将在分析器开始时执行,以禁用提示功能。
HintsfixedPointResolveJoinStrategyHints允许的连接策略提示列表在 JoinStrategyHint.strategies 中定义,连接策略提示可以指定关系别名序列,例如 “MERGE(a, c)”、“BROADCAST(a)”。连接策略提示计划节点将被插入任何与指定名称相匹配的关系(没有不同的别名)、子查询或公共表表达式的顶部。
提示解析的工作方式是向下递归遍历查询计划,找到与指定关系别名之一匹配的关系或子查询。遍历不会超出任何视图引用、子查询别名。
该规则必须在普通表表达式之前执行。
ResolveCoalesceHintsCOALESCE Hint 提示接受名称 “COALESCE”、“REPARTITION ”和 “REPARTITION_BY_RANGE”。
Simple Sanity CheckOnceLookupFunctions检查 UnresolvedFunction 引用的函数标识符是否在函数注册表中定义。请注意,该规则不会尝试解析 UnresolvedFunction。它只是根据函数标识符执行简单的存在性检查,以快速识别未定义的函数,而不会触发关系解析,这在某些情况下可能会导致昂贵的分区/模式发现过程。为了避免重复查找外部函数,外部函数标识符将存储在本地哈希集 externalFunctionNameSet 中。
Keep Legacy OutputsOnceKeepLegacyOutputsspark.sql.legacy.keepCommandOutputSchema为true时,保留 SQL 命令传统输出的规则。ShowTables,ShowNamespaces,DescribeNamespace,ShowTableProperties。
ResolutionfixedPointResolveCatalogs解析table/view/function/namespace的名称部分目录。
ResolveUserSpecifiedColumns解析用户指定的列。当用户在 INSERT INTO 中指定列列表时,为 DSv1 提供了重新排列列顺序的特殊规则。DSv2 由 Analyzer.ResolveInsertInto 单独处理。ResolveInsertInto 单独处理。
ResolveInsertInto解析INSERT INTO语句
ResolveRelations用catalog中的具体关系替换未解决的关系(表和视图)。
ResolvePartitionSpec在分区相关命令中将UnresolvedPartitionSpec解析成ResolvedPartitionSpec
ResolveFieldNameAndPosition根据命令的大小写敏感性解析、规范化和重写字段名称的规则。
AddMetadataColumns当节点缺少已解析的属性时,为子关系的输出添加元数据列。
元数据列的引用是使用 LogicalPlan.metadataOutput 中的列来解析的,但在关系被替换之前,关系的输出不包括元数据列。除非此规则将元数据添加到关系的输出中,否则分析器会检测到没有产生这些列。
只有当节点已解析但缺少其子节点的输入时,该规则才会添加元数据列。这样可以确保除非使用了元数据列,否则不会将其添加到计划中。通过只检查已解析的节点,可确保 * 扩展已完成,这样元数据列就不会被 * 意外选中。此规则会向下解析操作符,以避免过早投影出元数据列。
DeduplicateRelationsLogicalPlan的关系去重
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的名称是从封装GeneratorAliasMultiAlias表达式中提取的。
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 语句。如果可以,优化器将放弃重写的计划,并允许数据源使用过滤器删除。
typeCoercionRulesspark.sql.ansi.enabled设置为 true 的时候,采取 ANSI 的方式进行解析,这代表的是一组解析规则。
ResolveWithCTE使用相应 CTE 定义的解析输出属性更新 CTE 引用。
Remove TempResolvedColumnOnceRemoveTempResolvedColumn主解析批次中的 ResolveReferences 规则会在 UnresolvedHaving/ Filter/ Sort 中创建 TempResolvedColumn,用于保存临时解析的带有 agg.
如果托管 TempResolvedColumn 的表达式已完全解析,则规则 ResolveAggregationFunctions 将 - 如果 TempResolvedColumn 位于聚合函数或分组表达式中,则用 AttributeReference 替换 TempResolvedColumn。- 如果 TempResolvedColumn 不在聚合函数或分组表达式中,则将其标记为已尝试,希望其他规则能重新解决它。如果 hasTried 为真,ResolveReferences 将重新解析 TempResolvedColumn,如果解析失败,则保持不变。我们应该将其转回 UnresolvedAttribute,这样分析器稍后就能报告缺少列的错误。
如果托管 TempResolvedColumn 的表达式未被解析,TempResolvedColumn 将保持 hasTried 为 false。我们应该剥离 TempResolvedColumn,这样用户就能看到表达式未解析的原因,例如类型不匹配。
Post-Hoc ResolutionOnceResolveCommandsWithIfExists用于在未解析表或临时视图时处理命令的规则。这些命令支持 “ifExists ”标志,因此在未解析关系时不会失败。如果 “ifExists ”标志被设为 true,则该计划将被解析为 NoopCommand.
Remove Unresolved HintsOnceRemoveAllHints删除所有hits,用于删除用户提供的无效hits。必须在执行完所有其他hits规则后才能执行。
NondeterministicOncePullOutNondeterministic从非 Project 或过滤器的 LogicalPlan 中提取非确定表达式,将其放入内部 Project,最后将其投射到外部 Project。
UDFOnceHandleNullInputsForUDF通过添加额外的 If 表达式来进行空值检查,从而正确处理 UDF 的空基元输入。当用户使用基元参数定义 UDF 时,无法判断基元参数是否为空,因此我们假定基元输入为可传递的空,如果输入为空,则返回空。
ResolveEncodersInUDF通过明确给出属性来解决 UDF 的编码器问题。我们明确给出属性是为了处理输入值的数据类型与编码器内部模式不一致的情况,这可能会导致数据丢失。例如,如果实际数据类型是 Decimal(30,0),编码器不应将输入值转换为 Decimal(38,18)。
解析后的编码器将用于将内部行反序列化为 Scala 值。
UpdateNullabilityOnceUpdateAttributeNullability通过使用子输出属性(Attributes)中相应属性的无效性,更新已解析逻辑计划(LogicalPlan)中属性的无效性。之所以需要这一步骤,是因为用户可以在数据集 API 中使用已解析的 AttributeReference,而外连接可以改变 AttributeReference 的无效性。如果没有这条规则,可空列的可空字段实际上可能会被设置为不可空,从而导致非法优化(如 NULL 传播)和错误答案。

有关这种情况的具体查询,请参见 SPARK-13484 和 SPARK-13801。
SubqueryOnceUpdateOuterReferences引用外部查询块的子查询中的聚合表达式会被推送到外部查询块进行评估。下面的规则更新了此类外部引用,如 AttributeReference 引用父查询块/外部查询块中的属性。
CleanupfixedPointCleanupAliases清除计划中不必要的别名。基本上,我们只需要在 Project(项目列表)或 Aggregate(聚合表达式)或 Window(窗口表达式)中将别名作为顶层表达式。请注意,如果一个表达式有其他不在其子表达式中的表达式参数,如 RuntimeReplaceable,则本规则中的别名转换对这些参数不起作用。
HandleSpecialCommandOnceHandleSpecialCommand用于处理分析完成后需要通知的特殊命令的规则。该规则应在所有其他分析规则运行后运行。
Remove watermark for batch queryOnceEliminateEventTimeWatermark忽略批量查询中的事件时间水印,该功能仅在结构化数据流中支持。TODO:将此规则添加到分析器规则列表中。

optimization阶段使用的规则

操作优化的规则批 operatorOptimizationBatch

  • 算子下推
  • 算子合并
  • 常量折叠和强度消减
  • 过滤推断
  • 过滤推断后的算子优化
  • 下推join的额外谓词
规则批策略规则说明
Operator Optimization before Inferring FiltersfixedPointPushProjectionThroughUnion将Project操作符推送到Union操作符的两侧。可安全下推的操作如下所示。Union:现在,Union就意味着Union ALL,它不消除重复行。因此,通过它下推Filter和Project是安全的。下推Filter是由另一个规则PushDownPredicates处理的。一旦我们添加了UNION DISTINCT,我们就无法下推Project了。
PushProjectionThroughLimit将Project操作符下推到Limit操作符。
ReorderJoin重新排列连接的顺序,将所有条件推入Join,使最下面的连接至少有一个条件。
如果所有连接都至少有一个条件,则连接顺序不会改变。
如果启用了星形模式检测,则会根据启发式方法对星形连接计划重新排序。
EliminateOuterJoin1. 如果谓词可以限制结果集,从而消除所有空行,则消除外部连接
2. 如果聚合来自流式侧且不考虑重复,则移除外部连接
3. 删除外连接
对于只选择左侧列的左外部连接,且右侧连接键是唯一的。
对于右外部连接,只选择右侧列,且左侧连接键是唯一的。
该规则应在下推 “过滤器 ”之前执行
PushDownPredicates普通操作符和连接的谓词下推统一版本。该规则提高了级联Join(如:过滤-连接-连接-连接)的谓词下推性能: Filter-Join-Join-Join。大多数谓词可以一次性下推。
PushDownLeftSemiAntiJoin该规则是 PushPredicateThroughNonJoin 的变体,可以处理以下操作符下面的左半连接和左反连接。1) 项目 2) 窗口 3) 联合 4) 聚合 5) 其他允许的一元操作符。请参阅 PushPredicateThroughNonJoin。
PushLeftSemiLeftAntiThroughJoin该规则是 PushPredicateThroughJoin 的变体,可以处理连接操作符下面的左半连接和左反连接。允许的连接类型有 1) 内连接 2) 交叉连接 3) 左外连接 4) 右外连接
LimitPushDown下推UNION ALLJOIN下的LocalLimit
LimitPushDownThroughWindow下推Window下方的LocalLimit
ColumnPruning试图消除从查询计划中读取不需要的列。
GenerateOptimization如果生成的project不引用任何生成的属性(例如,对已爆炸数组进行类似计数的聚合),则从生成中删除不必要的字段。
CollapseRepartition合并相邻的RepartitionOperationRebalancePartitions运算符
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]),后者速度更快
OptimizeRandRand() 生成的随机列的 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 FiltersOnceInferFiltersFromGenerate从Generate中推导出过滤器,从而可以在连接前和数据源中提前删除Generate本应删除的行。
InferFiltersFromConstraints从操作符的现有约束中生成附加筛选器列表,但要移除那些已经是操作符条件一部分或操作符子约束一部分的筛选器。这些筛选器目前插入到筛选运算符中的现有条件以及连接运算符的两侧。
注意:虽然这种优化适用于很多类型的连接,但它主要有利于内部连接和左半连接。
Operator Optimization after Inferring FiltersfixedPointOperator Optimization before Inferring Filters一样
Push extra predicate through joinfixedPointPushExtraPredicateThroughJoin尝试将析取连接条件下推到左右子项中。为了避免扩展连接条件,即使发生谓词下推,连接条件也会保持原来的形式。
PushDownPredicates普通操作符和连接的谓词下推统一版本。该规则提高了级联Join(如:过滤-连接-连接-连接)的谓词下推性能: Filter-Join-Join-Join。大多数谓词可以一次性下推。

算子合并

规则批策略规则说明
Operator Optimization before Inferring FiltersfixedPointPushProjectionThroughUnion将Project操作符推送到Union操作符的两侧。可安全下推的操作如下所示。Union:现在,Union就意味着Union ALL,它不消除重复行。因此,通过它下推Filter和Project是安全的。下推Filter是由另一个规则PushDownPredicates处理的。一旦我们添加了UNION DISTINCT,我们就无法下推Project了。

Finish Analysis: 对包括所有子查询在内的整个计划应用完成分析规则。

规则批策略规则说明
Finish AnalysisOnceEliminateResolvedHint替换计划中的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 DistinctOnceEliminateDistinct删除无用的 DISTINCT:
对于某些集合表达式,例如 最大值和最小值。2. 如果子代保证了不同语义。
此规则应在 RewriteDistinctAggregates 之前应用。
Inline CTEOnceInlineCTE如果满足条件之一,则将 CTE 定义内联到相应的引用中: 1. CTE 定义不包含任何非确定表达式或包含对外部查询的属性引用。如果此 CTE 定义引用了另一个具有非确定表达式的 CTE 定义,则仍可内联当前 CTE 定义。2. 在整个主查询和所有子查询中,CTE 定义只被引用一次。
出现在子查询中且未内联的 CTE 定义将被上拉到主查询级别。
UnionfixedPointRemoveNoopOperators从查询计划中删除不做任何修改的禁用操作符。
CombineUnions将所有相邻的联合运算符合并为一个联合运算符。
RemoveNoopUnionSmplify Union 的子节点,或从查询计划中删除不对查询做任何修改的 no-op Union。
LocalRelation earlyfixedPointConvertToLocalRelation将 LocalRelation 上的本地操作(即不需要交换数据的操作)转换为另一个 LocalRelation。
PropagateEmptyRelation该规则在普通优化器中运行, 简化了空或非空关系的查询计划。
UpdateAttributeNullability通过使用子输出属性(Attributes)中相应属性的无效性,更新已解析逻辑计划(LogicalPlan)中属性的无效性。之所以需要这一步骤,是因为用户可以在数据集 API 中使用已解析的 AttributeReference,而外连接可以改变 AttributeReference 的无效性。如果没有这条规则,可空列的可空字段实际上可能会被设置为不可空,从而导致非法优化(如 NULL 传播)和错误答案。

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

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

有关这种情况的具体查询,请参见 SPARK-13484 和 SPARK-13801。
Optimize One Row PlanfixedPointOptimizeOneRowPlan该规则同时适用于普通优化器和 AQE 优化器。它使用最大行数优化计划:
如果排序子代的最大行数小于或等于 1,则删除排序
如果局部排序的子代每个分区的最大行数小于或等于 1,则删除局部排序
如果聚合子代的最大行数小于或等于 1,且其子代仅分组(包括重写的独特计划),则将聚合转换为项目
如果聚合子代的最大行数小于或等于 1,在所有聚合表达式中将 distinct 设置为 false
Check Cartesian ProductsOnceCheckCartesianProducts
RewriteSubqueryOnceRewritePredicateSubquery该规则可将谓词子查询改写为左半连接/反连接。支持以下谓词:a. EXISTS/ NOT EXISTS 将被改写为半连接/反连接,过滤器中未解决的条件将被提取出来作为连接条件。b. IN/ NOT IN 将被改写为半连接/反连接,过滤器中未解决的条件将被提取出来作为连接条件,值 = 所选列也将用作连接条件。
PushPredicateThroughJoin下推筛选运算符,其中的条件只能使用连接左侧或右侧的属性进行评估。其他筛选条件被移到连接条件中。
同时下推连接筛选器,在适用情况下,只需使用子查询左侧或右侧的属性即可对条件进行评估。
LimitPushDown下推UNION ALLJOIN下的LocalLimit
ColumnPruning试图消除从查询计划中读取不需要的列。
CollapseProject将所有相邻的union运算符合并为一个union运算符。
RemoveRedundantAliases从查询计划中删除冗余别名。冗余别名是指不更改列名或元数据,也不重复列的别名。
RemoveNoopOperators从查询计划中删除不做任何修改的禁用操作符。
NormalizeFloatingNumbersOnceNormalizeFloatingNumbers
ReplaceUpdateFieldsExpressionOnceReplaceUpdateFieldsExpression用an evaluable expression替换 UpdateFields 表达式。
RuleExecutor
Analyzer
Substitution
DisableHints
Hints
SimpleSanityCheck
KeepLegacyOutputs
Resolution
RemoveTempResolvedColumn
Post-HocResolution
RemoveUnresolvedHints
Nondeterministic
UDF
UpdateNullability
Subquery
Cleanup
HandleSpecialCommand
RemovewatermarkForBatchQuery
Optimizer
EliminateDistinct
InlineCTE
Union
PullupCorrelatedExpressions
Subquery
ReplaceOperators
Aggregate
CleanUpTemporaryCTEInfo
PreCBORules
EarlyFilterandProjectionPush-Down
UpdateCTERelationStats
JoinReorder
EliminateSorts
DecimalOptimizations
DistinctAggregateRewrite
ObjectExpressionsOptimization
LocalRelation
OptimizeOneRowPlan
CheckCartesianProducts
RewriteSubquery
NormalizeFloatingNumbers
ReplaceUpdateFieldsExpression
OperatorOptimizationBeforeInferringFilters
InferFilters
OperatorOptimizationAfterInferringFilters
PushExtraPredicateThroughjoin
RuleId
RuleIdCollection

相关文章:

【Spark源码分析】规则框架-草稿

规则批&#xff1a;规则集合序列&#xff0c;由名称、执行策略、规则列表组成。一个规则批里使用一个执行规则。 执行策略 FixedPointOnce 规则&#xff1a; #mermaid-svg-1cvqR4xkYpMuAs77 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px…...

迪米特原则的理解和实践

迪米特原则&#xff08;Law of Demeter&#xff0c;简称LoD&#xff09;&#xff0c;也被称为最少知识原则&#xff08;Least Knowledge Principle&#xff0c;LKP&#xff09;&#xff0c;是面向对象设计中的一个重要原则。其核心思想是&#xff1a;一个对象应该对其他对象有最…...

jQuery零基础入门速通(中)

大家好&#xff0c;我是小黄。 在上一篇文章中&#xff0c;我们初步了解了jQuery的基本概念、环境搭建、选择器、基本的DOM操作以及事件处理。接下来&#xff0c;我们将继续深入探讨jQuery的DOM操作和事件处理&#xff0c;以及一些实用的技巧和高级用法。 五、高级DOM操作 5…...

【设计模式系列】中介者模式(十八)

一、什么是中介者模式 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;其核心思想是通过一个中介者对象来封装一系列对象之间的交互&#xff0c;使这些对象不需要相互显式引用。中介者模式提供了一个中介层&#xff0c;用以协调各个对象…...

PDF版地形图矢量出现的问题

项目描述&#xff1a;已建风电场道路测绘项目&#xff0c;收集到的数据为PDF版本的地形图&#xff0c;图上标注了项目竣工时期的现状&#xff0c;之后项目对施工区域进行了复垦恢复地貌&#xff0c;现阶段需要准确的知道实际复垦修复之后的道路及其它临时用地的面积 解决方法&…...

小迪安全第四十二天笔记 简单的mysql注入 mysql的基础知识 用户管理数据库模式 mysql 写入与读取 跨库查询

前言 之前的安全开发我们学习了 php联动数据库的模式 &#xff0c;这个模式是现在常用的模式 这一节来学习 如何 进行数据库的注入和数据库相关知识 1、了解数据库的结构 我们使用 navicate连接数据库之后看一下 一共四层结构 库 》表》字段》数据 这个层级关系…...

11.25.2024刷华为OD

文章目录 HJ76 尼科彻斯定理&#xff08;观察题&#xff0c;不难&#xff09;HJ77 火车进站&#xff08;DFS&#xff09;HJ91 走格子方法&#xff0c;&#xff08;动态规划&#xff0c;递归&#xff0c;有代表性&#xff09;HJ93 数组分组&#xff08;递归&#xff09;语法知识…...

你真的会用饼图吗?JVS-智能BI饼图组件深度解析

在数据可视化的世界里&#xff0c;饼图是我们常见的一种可视化图形。在JVS-智能BI中提供了数据可视化饼图组件&#xff0c;接下来我通过这篇文章详细介绍&#xff0c;从配色方案到图形配置&#xff0c;从显示数据到提示信息&#xff0c;饼图的每一个细节配置。 饼图类图表概述…...

HarmonyOS Next 模拟器安装与探索

HarmonyOS 5 也发布了有一段时间了&#xff0c;不知道大家实际使用的时候有没有发现一些惊喜。当然随着HarmonyOS 5的更新也带来了很多新特性&#xff0c;尤其是 HarmonyOS Next 模拟器。今天&#xff0c;我们就来探索一下这个模拟器&#xff0c;看看它能给我们的开发过程带来什…...

医学机器学习:数据预处理、超参数调优与模型比较的实用分析

摘要 本文介绍了医学中的机器学习&#xff0c;重点阐述了数据预处理、超参数调优和模型比较的技术。在数据预处理方面&#xff0c;包括数据收集与整理、处理缺失值、特征工程等内容&#xff0c;以确保数据质量和可用性。超参数调优对模型性能至关重要&#xff0c;介绍了多种调…...

单片机知识总结(完整)

1、单片机概述 1.1. 单片机的定义与分类 定义&#xff1a; 单片机&#xff08;Microcontroller Unit&#xff0c;简称MCU&#xff09;是一种将微处理器、存储器&#xff08;包括程序存储器和数据存储器&#xff09;、输入/输出接口和其他必要的功能模块集成在单个芯片上的微型…...

【C++】auto和decltype类型推导关键字

1.C11关键字 auto和decltype是C11引入的关键字&#xff0c;负责类型的推导。所有不同的是&#xff1a; auto可直接用来定义变量&#xff0c;编译器会自动推导出变量的类型。decltype是推导出一个操作数的类型&#xff0c;然后用这个类型再去定义。 2.两者区别 尽管两者都是宏…...

OGRE 3D----3. OGRE绘制自定义模型

在使用OGRE进行开发时,绘制自定义模型是一个常见的需求。本文将介绍如何使用OGRE的ManualObject类来创建和绘制自定义模型。通过ManualObject,开发者可以直接定义顶点、法线、纹理坐标等,从而灵活地构建各种复杂的几何体。 Ogre::ManualObject 是 Ogre3D 引擎中的一个类,用…...

ARM + Linux 开发指南

随想:想写一个系列来讲如何嵌入式开发,然后能形成一个知识体系,帮助那些刚刚做嵌入开发的同学们. 1. ARM Linux从开机到Linux完全启动的流程和代码分析 ARM Linux从开机到完全启动的流程与代码分析 ARM Linux的启动过程主要涉及从设备上电开始,到Linux内核完全启动并进入…...

facebook欧洲户开户条件有哪些又有何优势?

在当今数字营销时代&#xff0c;Facebook广告已成为企业推广产品和服务的重要渠道。而为了更好地利用这一平台&#xff0c;广告主们需要理解不同类型的Facebook广告账户。Facebook广告账户根据其属性可分为多种类型&#xff0c;包括个人广告账户、企业管理&#xff08;BM&#…...

算法训练(leetcode)二刷第三十一天 | 1049. 最后一块石头的重量 II、494. 目标和、*474. 一和零

刷题记录 1049. 最后一块石头的重量 II*494. 目标和二维数组滚动数组 *474. 一和零 1049. 最后一块石头的重量 II leetcode题目地址 本题与416. 分割等和子集类似。依旧是01背包问题&#xff0c;本题尽可能将石头分为相等&#xff08;相近&#xff09;的两堆&#xff0c;然后…...

软件测试丨Pytest生命周期与数据驱动

Pytest的生命周期概述 Pytest 是一个强大的测试框架&#xff0c;提供了丰富的特性来简化测试执行。它的生命周期包括多个阶段&#xff0c;涉及从准备测试、执行测试到报告结果的完整流程。因此&#xff0c;理解Pytest的生命周期将帮助我们更好地设计和管理测试用例。 开始阶段…...

Figma入门-原型交互

Figma入门-原型交互 前言 在之前的工作中&#xff0c;大家的原型图都是使用 Axure 制作的&#xff0c;印象中 Figma 一直是个专业设计软件。 最近&#xff0c;很多产品朋友告诉我&#xff0c;很多原型图都开始用Figma制作了&#xff0c;并且很多组件都是内置的&#xff0c;对…...

网络安全防范技术

1 实践内容 1.1 安全防范 为了保障"信息安全金三角"的CIA属性、即机密性、完整性、可用性&#xff0c;信息安全领域提出了一系列安全模型。其中动态可适应网络安全模型基于闭环控制理论&#xff0c;典型的有PDR和P^2DR模型。 1.1.1 PDR模型 信息系统的防御机制能抵抗…...

Java - JSR223规范解读_在JVM上实现多语言支持

文章目录 1. 概述2. 核心目标3. 支持的脚本语言4. 主要接口5. 脚本引擎的使用执行JavaScript脚本执行groovy脚本1. Groovy简介2. Groovy脚本示例3. 如何在Java中集成 Groovy4. 集成注意事项 6. 与Java集成7. 常见应用场景8. 优缺点9. 总结 1. 概述 JSR223&#xff08;Java Spe…...

win10系统部署RAGFLOW+Ollama教程

本篇主要基于linux服务器部署ragflowollama&#xff0c;其他操作系统稍有差异但是大体一样。 一、先决条件 CPU ≥ 4核&#xff1b; RAM ≥ 16 GB&#xff1b; 磁盘 ≥ 50 GB&#xff1b; Docker ≥ 24.0.0 & Docker Compose ≥ v2.26.1。 如果尚未在本地计算机&#xff…...

基于Python制作一个简易UI界面

基于Python制作一个简易UI界面 目录 基于Python制作一个简易UI界面1 原理简介2 编写程序3 程序测试 1 原理简介 这里用到了Python自带的UI库tkinter。 tkinter 是 Python 的标准 GUI&#xff08;图形用户界面&#xff09;库&#xff0c;用于创建和管理图形界面。它提供了一个简…...

鲁菜大师程伟华到访金宫川派味业

共工新闻社11月29日电&#xff08;范琦&#xff09;上周&#xff0c;中国鲁菜大师、首批中国烹饪大师名厨程伟华到访金宫川派味业总部基地。这位从厨51年、坚持传承鲁菜的行业大师人物&#xff0c;深入了解了金宫川派的品牌文化&#xff0c;参观了金宫自动生产车间&#xff0c;…...

Linux设置jar包开机自启动

本文详细描述了如何在Linux服务器上创建并配置jar包的自启动脚本&#xff0c;包括编辑/etc/init.d/jar_auto.sh以设置环境变量&#xff0c;将jar包添加到rc.local以开机启动&#xff0c;以及提升脚本文件权限确保自动执行。 1、准备工作 Linux中Java的路径 项目jar包绝对路径 2…...

IoTDB 常见问题 QA 第一期

开始&#xff01;关于 IoTDB 的 Q&A 我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;WAL 堆积导致写入失败 问题及现象 集群报错&#xff1a; The write is rejec…...

【linux学习指南】linux捕捉信号

文章目录 &#x1f4dd;前言&#x1f320; 信号捕捉的流程&#x1f309; sigaction &#x1f320;穿插话题-操作系统是怎么运⾏的&#x1f309; 硬件中断&#x1f309;时钟中断 &#x1f6a9;总结 &#x1f4dd;前言 &#x1f320; 信号捕捉的流程 如果信号的处理动作是⽤⼾⾃定…...

git如何快速拉取已经提交的mr进行验证

参考&#xff1a;https://stackoverflow.com/questions/44992512/how-to-checkout-merge-request-locally-and-create-new-local-branch Pull merge request to new branch git fetch origin merge-requests/REQUESTID/head:BRANCHNAME i.e git fetch origin merge-requests/…...

【阿来来gis规划师工具箱说明书】h07四分标注

背景 在做arcmap的四分标注前&#xff0c;已经做好了二行三行的标注&#xff0c;以及在pro中做好了四分标注。这个四分标注做了好些版本&#xff0c;都达不到想要的效果。最终使用了静态标注的形式来做。 制作思路 新建两个承接标注文字的文本字段&#xff0c;考虑一般标注超…...

【大数据学习 | 面经】HDFS的三副本机制和编码机制

1. hdfs的三副本机制 hdfs的三副本机制是其核心特性之一&#xff0c;旨在确保数据的高可用性和容错性。通过将每个文件的数据块复制三个副本&#xff0c;并分散存储在不同的DateNode上&#xff0c;hdfs能够在节点故障的时候提供数据冗余和持续访问的能力。 三副本机制的工作原…...

lua-cjson 例子

apt install -y lua-cjson 安装 编辑 tmp.lua cjson require "cjson" p 666 d "23.42" payload{"d":[{"pres":..(p)..,"temp":"..(d).."}]} print("payload " .. payload) j cjson.decode(payloa…...

新浪sae可以做网站么/北京优化网站公司

一:相关知识 WPF资源系统 1、资源定义 对我们开发有用的东西 都 叫资源 2、程序集资源 XAML-》BAML 寻址系统不同 3、对象资源 程序集资源 添加 引用 Pack URI Pack://application:,/程序集名称;版本号;公钥;component/Images/Logo.png 音视频文件 对象资源 1、保管与引用 保…...

网站制作怎么把网站交付/郑州网站seo公司

描述 有 n 个硬币排成一条线。两个参赛者轮流从右边依次拿走 1 或 2 个硬币&#xff0c;直到没有硬币为止。拿到最后一枚硬币的人获胜。 请判定 先手玩家 必胜还是必败? 若必胜, 返回 true, 否则返回 false. 样例 - 样例 1:输入: 1 输出: true- 样例 2:输入: 4 输出: tru…...

南宁cms建站系统/bt兔子磁力搜索引擎最新版

题目传送门 题目大意&#xff1a; 我去好长啊不写了qwq 题解 NOIp 太恶心了&#xff0c;又出了一道模板题&#xff0c;这告诉了我们多刷板子的重要性。 没错&#xff0c;这是个动态dp的模板。 这题的转移方程为&#xff1a; {fi,0∑fson,1fi,1vali∑max⁡(fson,0,fson,1)\…...

ps拼合网站截图怎么做/广告外链购买交易平台

微信双开一般来说问题不大&#xff0c;但仍需节制覆盖全平台&#xff1a;Windows、Mac、iOS、Android微信&#xff0c;这个App&#xff0c;已经成为了不可或缺的存在&#xff1b;而越来越多的朋友拥有不止一个微信号。为了适应这个趋势&#xff0c;越来越多手机支持微信双开&am…...

北京餐饮培训网站建设/端口扫描站长工具

供应商管理是一个术语&#xff0c;描述企业管理其供应商的过程&#xff0c;这些供应商又被称作供货商。供应商管理包括选择供应商、谈判合同、控制成本、减少与供应商有关的风险以及确保服务交付等活动。 企业使用的供应商因组织性质的不同而有很大不同&#xff0c;可能包括不…...

搭建企业网站需要什么/东莞公司seo优化

必须要有注释 必须要有四个字段 id,create_time,create_user,update_time,update_user 尽量自动赋值 id,create_time,update_time 更新时间赋值较为复杂 先创建函数&#xff0c;该函数可以复用给所有表&#xff0c;但是每个表需要有update_time字段 CREATE OR REPLACE F…...