SparkSQL之Optimized LogicalPlan生成过程
经过Analyzer的处理,Unresolved LogicalPlan已经解析成为Analyzed LogicalPlan。Analyzed LogicalPlan中自底向上节点分别对应Relation、Subquery、Filter和Project算子。
Analyzed LogicalPlan基本上是根据Unresolved LogicalPlan一对一转换过来的,对于SQL语句中的逻辑能够很好地表示。然而,在实际应用中,很多低效的写法会带来执行效率的问题,需要进一步对Analyzed LogicalPlan进行处理,得到更优的逻辑算子树。于是,针对SQL逻辑算子树的优化器Optimizer应运而生。
Optimizer概述
在分析Rule体系时就已经提到,Optimizer同样继承自RuleExecutor类,本身没有重载RuleExecutor中的execute方法,因此其执行过程仍然是调用其父类RuleExecutor中实现的execute方法。在QueryExecution中,Optimizer会对传入的Analyzed LogicalPlan执行execute方法,启动优化过程。
val optimizedPlan: LogicalPlan = optimizer.execute(analyzed)
与Analyzer类似,Optimizer的主要机制也依赖重新定义的一系列规则,同样对应RuleExecutor类中的成员变量batches,因此在RuleExecutor执行execute方法时会直接利用这些规则Batch。
如图1 所示,Optimizer继承自RuleExecutor,而SparkOptimizer又继承自Optimizer。在上述代码中,optimizer即是构造的SparkOptimizer类。从图中可以看出,Optimizer本身定义了12个规则Batch,在SparkOptimizer类中又添加了4个Batch。
Optimizer 规则体系
Spark 2.1版本的SparkOptimizer中共实现了16个Batch,其中包含了53条优化规则,本节对这些优化规则进行系统的分析。
(1)Batch Finish Analysis
该Batch包含5条优化规则,分别是EliminateSubqueryAliases、ReplaceExpressions、ComputeCurrentTime、GetCurrentDatabase和RewriteDistinctAggregates,这些规则都只执行一次。
① EliminateSubqueryAliases:消除子查询别名,对应逻辑算子树中的SubqueryAlias节点。一般来讲,Subqueries仅用于提供查询的视角范围(Scope)信息,一旦Analyzer阶段结束,该节点就可以被移除,该优化规则直接将SubqueryAlias替换为其子节点。
② ReplaceExpressions:表达式替换,在逻辑算子树中查找匹配RuntimeReplaceable的表达式并将其替换为能够执行的正常表达式。这条规则通常用来对其他类型的数据库提供兼容的能力,例如,可以用“coalesce”来替换支持“nvl”的表达式。
③ ComputeCurrentTime:计算与当前时间相关的表达式,在同一条SQL语句中可能包含多个计算时间的表达式,即CurrentDate和CurrentTimestamp,且该表达式出现在多个语句中。为避免不一致,ComputeCurrentTime对逻辑算子树中的时间函数计算一次后,将其他同样的函数替换成该计算结果。
④ GetCurrentDatabase:获取当前数据库,在SQL语句中可能会调用CurrentDatabase函数来获取Catalog中的当前数据库,而这个方法没必要在执行阶段再进行计算。GetCurrentDatabase规则执行CurrentDatabase并得到结果,然后用此结果替换所有的CurrentDatabase表达式。
⑤ RewriteDistinctAggregates:重写Distinct聚合操作,对于包含Distinct算子的聚合语句,这条规则将其转换为两个常规的聚合表达式。
严格来讲,Finish Analysis这个Batch中的一些规则更多的是为了得到正确的结果(例如ComputeCurrentTime),并不涉及优化操作,从逻辑上更应该归于Analyzer的分析规则中。但是考虑到Analyzer中会进行一些规范化的操作,因此将EliminateSubqueryAliases和ComputeCurrentTime规则放在优化的部分,实际上真正的优化过程从下一个Batch开始。
(2)Batch Union⇒CombineUnions
针对Union操作的规则Batch,中间包含一条CombineUnions优化规则。在逻辑算子树中,当相邻的节点都是Union算子时,可以将这些相邻的Union节点合并为一个Union节点。在该规则中,flattenUnion是核心方法,用栈实现了节点的合并。需要注意的是,后续的优化操作可能会将原来不相邻的Union节点变得相邻,因此在后面的规则Batch中又加入了CombineUnions这条规则。
(3)Batch Subquery⇒OptimizeSubqueries
该Batch目前只包含OptimizeSubqueries这一条优化规则。当SQL语句包含子查询时,会在逻辑算子树上生成SubqueryExpression表达式。OptimizeSubqueries优化规则在遇到Subquery-Expression表达式时,进一步递归调用Optimizer对该表达式的子计划并进行优化。
(4)Batch ReplaceOperators
该Batch中的优化规则主要用来执行算子的替换操作。在SQL语句中,某些查询算子可以直接改写为已有的算子,避免进行重复的逻辑转换。Replace Operators中包含ReplaceIntersectWithSemiJoin、ReplaceExceptWithAntiJoin和ReplaceDistinctWithAggregate这3条优化规则。
① ReplaceIntersectWithSemiJoin:将Intersect操作算子替换为Left-Semi Join操作算子,从逻辑上来看,这两种算子是等价的。需要注意的是,ReplaceIntersectWithSemiJoin优化规则仅适用于INTERSECTDISTINCT类型的语句,而不适用于INTERSECTALL语句。此外,该优化规则执行之前必须消除重复的属性,避免生成的Join条件不正确。
② ReplaceExceptWithAntiJoin:将Except操作算子替换为Left-Anti Join操作算子,从逻辑上来看,这两种算子是等价的。与上一条优化规则一样,ReplaceExceptWithAntiJoin优化规则仅适用于EXCEPTDISTINCT类型的语句,而不适用于EXCEPTALL语句。此外,该优化规则执行之前必须消除重复的属性,避免生成的Join条件不正确。
③ ReplaceDistinctWithAggregate:该优化规则会将Distinct算子转换为Aggregate语句。在某些SQL语句中,Select直接进行Distinct操作,这种情况下可以将其直接转换为聚合操作。ReplaceDistinctWithAggregate规则会将Distinct算子替换为对应的Group By语句。
从以上描述中可以看出,ReplaceOperators主要针对的是集合类型的操作算子。
(5)Batch Aggregate
该Batch主要用来处理聚合算子中的逻辑,包括RemoveLiteralFromGroupExpressions和RemoveRepetitionFromGroupExpressions两条规则。RemoveLiteralFromGroupExpressions优化规则用来删除Group By语句中的常数,这些常数对于结果无影响,但是会导致分组数目变多。此外,如果Group By语句中全部是常数,则会将其替换为一个简单的常数0表达式。RemoveRepetitionFromGroupExpressions优化规则将重复的表达式从Group By语句中删除,同样对结果无影响。
(6)Batch Operator Optimizations
类似Analyzer中的Operator解析规则,该Batch包含了Optimizer中数量最多同时也是最常用的各种优化规则,共31条。从整体来看,这31条优化规则(如表1所示)可以分为3个模块:算子下推(Operator Push Down)、算子组合(Operator Combine)、常量折叠与长度削减(Constant Folding and Strength Reduction)。
算子下推:算子下推是数据库中常用的优化方式,表1中所列的前8条规则都属于算子下推的模块。顾名思义,算子下推所执行的优化操作主要是将逻辑算子树中上层的算子节点尽量下推,使其靠近叶子节点,这样能够在不同程度上减少后续处理的数据量甚至简化后续的处理逻辑。以常见的列剪裁(ColumnPruning)优化为例,假设数据表中有A、B、C 3列,但是查询语句中只涉及A、B两列,那么ColumnPruning将会在读取数据后剪裁出这两列。又如Lim itPushDown优化规则,能够将LocalLimit算子下推到Union All和Outer Join操作算子的下方,减少这两种算子在实际计算过程中需要处理的数据量。
算子组合:算子组合类型的优化规则将逻辑算子树中能够进行组合的算子尽量整合在一起,避免多次计算,以提高性能。表1中间6条规则(从CollapseRepartition到CombineUnions)都属于算子组合类型的优化。可以看到这些规则主要针对的是重分区(repartition)算子、投影(Project)算子、过滤(Filter)算子、Window算子、Limit算子和Union算子,其中CombineUnions在之前已经提到过。需要注意的是,这些规则主要针对的是算子相邻的情况。
常量折叠与长度削减:对于逻辑算子树中涉及某些常量的节点,可以在实际执行之前就完成静态处理。常量折叠与长度削减类型的优化规则主要针对的就是这种情况。表1中的后17条优化规则都属于这种类型。例如,在ConstantFolding规则中,对于能够foldable(可折叠)的表达式会直接在EmptyRow上执行evaluate操作,从而构造新的Literal表达式;PruneFilters优化规则会详细地分析过滤条件,对总是能够返回true或false的过滤条件进行特别的处理。
(7)Batch Check Cartesian Products⇒CheckCartesianProducts
该Batch只有CheckCartesianProducts这一条优化规则,用来检测逻辑算子树中是否存在笛卡儿积类型的Join操作。如果存在这样的操作,而SQL语句中没有显示地使用cross join表达式,则会抛出异常。CheckCartesianProducts规则必须在ReorderJoin规则执行之后才能执行,确保所有的Join条件收集完毕。需要注意的是,当“spark.sql.crossJoin.enabled”参数设置为true时,该规则会被忽略。
(8)Batch DecimalOptim izations⇒DecimalAggregates
该Batch只有DecimalAggregates这一条优化规则,用于处理聚合操作中与Decimal类型相关的问题。一般情况下,如果聚合查询中涉及浮点数的精度处理,性能就会受到很大的影响。对于固定精度的Decimal类型,DecimalAggregates规则将其当作unscaled Long类型来执行,这样可以加速聚合操作的速度。
(9)Batch Typed Filter Optimization⇒CombineTypedFilters
该Batch仅包含CombineTypedFilters这一条优化规则,用来对特定情况下的过滤条件进行合并。当逻辑算子树中存在两个TypedFilter过滤条件且针对同类型的对象条件时,CombineTypedFilters优化规则会将它们合并到同一个过滤函数中。
(10)Batch LocalRelation⇒ConvertToLocalRelation|PropagateEmptyRelation
该Batch主要用来优化与LocalRelation相关的逻辑算子树,包含ConvertToLocalRelation和PropagateEmptyRelation两条优化规则。ConvertToLocalRelation将LocalRelation上的本地操作(不涉及数据交互)转换为另一个LocalRelation,目前该规则实现较为简单,仅处理Project投影操作。PropagateEmptyRelation优化规则会将包含空的LocalRelation进行折叠。
(11)Batch OptimizeCodegen⇒OptimizeCodegen
该Batch只有OptimizeCodegen这一条优化规则,用来对生成的代码进行优化。OptimizeCodegen规则主要针对的是casewhen语句,当casewhen语句中的分支数目不超过配置中的最大数目时,该表达式才能执行代码生成。
(12)Batch RewriteSubquery⇒RewritePredicateSubquery|CollapseProject
该Batch主要用来优化子查询,目前包含RewritePredicateSubquery和CollapseProject两条优化规则。RewritePredicateSubquery将特定的子查询谓词逻辑转换为left-semi/anti join操作。其中,EXISTS和NOTEXISTS算子分别对应semi和anti类型的Join,过滤条件会被当作Join的条件;IN和NOT IN也分别对应semi和anti类型的Join,过滤条件和选择的列都会被当作join的条件。CollapseProject优化规则比较简单,类似CombineTypedFilters优化规则,会将两个相邻的Project算子组合在一起并执行别名替换,整合成一个统一的表达式。
(13)Batch OptimizeMetadataOnly Query⇒OptimizeMetadataOnlyQuery
该Batch仅执行一次,只有OptimizeMetadataOnlyQuery这一条规则,用来优化执行过程中只需查找分区级别元数据的语句。需要注意的是,OptimizeMetadataOnlyQuery优化规则适用于扫描的所有列都是分区列且包含聚合算子的情形,而且聚合算子需要满足以下情况之一:聚合表达式是分区列;分区列的聚合函数有DISTINCT算子;分区列的聚合函数中是否有DISTINCT算子不影响结果。
(14)Batch Extract Python UDF from Aggregate⇒ExtractPythonUDFFrom Aggregate
该Batch仅执行一次,只有ExtractPythonUDFFrom Aggregate这一条规则,用来提取出聚合操作中的Python UDF函数。该规则主要针对的是采用PySpark提交查询的情形,将参与聚合的Python自定义函数提取出来,在聚合操作完成之后再执行。
(15)Batch Prune FileSource TablePartitions⇒PruneFileSourcePartitions
该Batch仅执行一次,只有PruneFileSourcePartitions这一条规则,用来对数据文件中的分区进行剪裁操作。当数据文件中定义了分区信息且逻辑算子树中的LogicalRelation节点上方存在过滤算子时,PruneFileSourcePartitions优化规则会尽可能地将过滤算子下推到存储层,这样可以避免读入无关的数据分区。
(16)Batch User Provided Optimizers⇒ExperimentalMethods.extraOptimizations
顾名思义,该Batch用于支持用户自定义的优化规则,其中ExperimentalMethods的extraOptim izations队列默认为空。可以看到,Spark SQL在逻辑算子树的转换阶段是高度可扩展的,用户只需要继承Rule[LogicalPlan]虚类,实现相应的转换逻辑就可以注册到优化规则队列中应用执行。
Optimized LogicalPlan的生成过程
上述内容对SparkOptimizer中的优化规则进行了系统概述,现在回到案例对应的Analyzed LogicalPlan。接下来,将会重点分析Optimzer对该逻辑算子树进行优化处理的具体流程。
对于案例生成的Analyzed LogicalPlan,首先执行的是Finish Analysis这个Batch中的Eliminate-SubqueryAliases优化规则,用来消除子查询别名的情形。
EliminateSubqueryAliases优化规则的实现逻辑如以下代码所示,可以看到,该规则的实现非常简单,直接将SubqueryAlias逻辑算子树节点替换为其子节点。经过EliminateSubqueryAliases规则优化后的逻辑算子树如图2所示。可见SubqueryAlias节点被删除,Filter节点直接作用于Relation节点。
object EliminateSubqueryAliases extends Rule[LogicalPlan] {def apply(plan: LogicalPlan): LogicalPlan = plan transformUp {case SubqueryAlias(_, child, _) = child }
}
第2步优化将匹配OperatorOptimizations这个Batch中的InferFiltersFromConstraints优化规则,用来增加过滤条件。InferFiltersFromConstraints优化规则会对当前节点的约束条件进行分析,生成额外的过滤条件列表,这些过滤条件不会与当前算子或其子节点现有的过滤条件重叠,具体实现如以下代码片段所示(注:案例逻辑算子树中不涉及Join查询语句,因此这里的代码片段中未包含Join算子的匹配部分)。
object InferFiltersFromConstraints extends Rule[LogicalPlan] with PredicateHelper {def apply(plan: LogicalPlan): LogicalPlan = plan transform {case filter @ Filter(condition, child) => val newFilters = filter.constraints -- (child.constraints ++ splitConjunctivePredicates(condition))if (newFilters.nonEmpty) {Filter(And(newFilters.reduce(And), condition), child)} else {filter}}
}
从上述代码逻辑可知,对于上一步生成的逻辑算子树中的Filter节点,会构造新的过滤条件(newFilter)。当新的过滤条件不为空时,会与现有的过滤条件进行整合,构造新的Filter逻辑算子节点。
经过InferFiltersFromConstraints规则优化之后的逻辑算子树如图3所示,Filter逻辑算子树节点中多了“isnotnull(age#0L)”这个过滤条件。该过滤条件来自于Filter中的约束信息,用来确保筛选出来的数据age字段不为null。
最后一步,上述逻辑算子树会匹配Operator Optimizations这个Batch中的ConstantFolding优化规则,对LogicalPlan中可以折叠的表达式进行静态计算直接得到结果,简化表达式。
object ConstantFoldingFolding extends Rule[LogicalPlan] {def apply(plan: LogicalPlan): LogicalPlan = plan transform {case q: LogicalPlan => q transformExpressionsDown {case l: Literal => lcase e if e.foldable => Literal.create(e.eval(EmptyRow), e.dataType)}}
}
在ConstantFolding规则中,如果LogicalPlan中的表达式可以折叠(foldable为true),那么会将EmptyRow作为参数传递到其eval方法中直接计算,然后根据计算结果构造Literal常量表达式。经过该规则优化后的逻辑算子树如图4所示。

可见,Filter过滤条件中的“cast(18,bigint)”表达式经过计算成为“Literal(18,bigint)”表达式,即输出的结果为18。在原来的Cast表达式中,其子节点Literal表达式的foldable值为true,因此Cast表达式本身的foldable值也为true,在匹配该优化规则时,Cast表达式会被直接计算。
经过上述步骤,Spark SQL逻辑算子树生成、分析与优化的整个阶段都执行完毕。最终生成的逻辑算子树包含Relation节点、Filter节点和Project节点,同时每个节点中又包含了由对应表达式构成的树。
相关文章:

SparkSQL之Optimized LogicalPlan生成过程
经过Analyzer的处理,Unresolved LogicalPlan已经解析成为Analyzed LogicalPlan。Analyzed LogicalPlan中自底向上节点分别对应Relation、Subquery、Filter和Project算子。 Analyzed LogicalPlan基本上是根据Unresolved LogicalPlan一对一转换过来的,…...

Java中有几种基本数据类型以及转换方式【Java面经(1)】
问:Java中有几种基本数据类型呢?以及它们之间的转换方式。详细介绍下 总共有8种基本数据类型 byte 、short 、long 、float 、double 、boolean 、char 详细类型以及字节数: 基本数据类型的转换方式 自动类型转换:小–>大 byt…...
JVM虚拟机:JVM调优第一步,了解JVM常用命令行参数
本文重点 从本文课程开始,我们将用几篇文章来介绍JVM中常用的命令行的参数,这个非常重要,第一我们可以通过参数了解JVM的配置,第二我们可以通过参数完成对JVM的调参。以及后面的JVM的调优也需要用到这些参数,所以我们…...

CSS特效019:图标图片悬浮旋转一周
CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧,主要包含CSS布局,CSS特效,CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点,CSS特效主要是一些动画示例,CSS花边是描述了一些CSS…...
requests请求django接口跨域问题处理
参考: https://zhuanlan.zhihu.com/p/416978320 https://blog.csdn.net/SweetHeartHuaZai/article/details/130983179 使用httpx代替requests import httpxheaders {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.3…...
#Js篇:Promise
定义 Promise是异步操作解决方案,为异步操作提供统一接口。 Promise英文意思是“承诺”,表示其他手段无法改变。 返回 所有异步任务都返回一个Promise实例。 Promise实例有一个then方法,用于指定下一步的回调函数。 状态 异步操作未完…...

【数据库篇】关系模式的表示——(2)规范化
范式:范式是符合某一种级别的关系模式的集合 规范化:是指一个低一级的范式的关系模式,通过模式的分解转换为若干个高一级范式的关系模式的集合。 1NF 每个分量必须是不可分开的数据项,满足这个条件的关系模式就是1NF。 2NF 若…...

【C++那些事儿】类与对象(3)
君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,我之前看过一套书叫做《明朝那些事儿》,把本来枯燥的历史讲的生动有趣。而C作为一门接近底层的语言,无疑是抽象且难度颇…...

spark的算子
spark的算子 1.spark的单Value算子 Spark中的单Value算子是指对一个RDD中的每个元素进行操作,并返回一个新的RDD。下面详细介绍一些常用的单Value算子及其功能: map:逐条映射,将RDD中的每个元素通过指定的函数转换成另一个值&am…...
【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷7
1、一袋小球中有15个白球,3个红球和2个黑球。在随机从袋子中拿出至少()个小球后,才可以保证至少拿出了5个白球 A、5 B、10 C、8 D、15 答案:B 2、以下选项中,数值最接近十进制数114的是( &…...

MySQL MHA高可用架构搭建
快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解(如有不正确的地方欢迎各位小伙伴在评论区提意见,博主会及时修改) MySQL MHA高可用架构搭建 MHA(Master HA)是一款开源的 MySQL 的高可用程序…...
UE小计:顶部工具栏按钮添加下拉列表,大纲列表、资源管理窗口右键添加按键
下拉列表 void FYouPluginsModule::StartupModule() {FYouToolStyle::Initialize();FYouToolStyle::ReloadTextures();FYouToolCommands::Register();PluginCommands MakeShareable(new FUICommandList);PluginCommands->MapAction(FYouToolCommands::Get().PackByCloudAc…...

git stash 用法总结
目录 1,介绍场景1:场景2: 2,常用命令2.1,基础2.2,进阶1,存储时指定备注2,通过索引来操作指定的存储3,修改存储规则 2.3,查看 stash 修改的具体内容 1…...

Linux操作系统之apt常用命令记录
文章目录 apt 命令apt 语法apt 常用命令列出所有可更新的软件清单命令升级软件包列出可更新的软件包及版本信息升级软件包,升级前先删除需要更新软件包安装指定的软件命令:安装多个软件包:更新指定的软件命令显示软件包具体信息,例如…...

TCP 重传、滑动窗口、流量控制、拥塞控制的剖析
TCP 是一个可靠传输的协议,那它是如何保证可靠的呢? 为了实现可靠性传输,需要考虑很多事情,例如数据的破坏、丢包、重复以及分片顺序混乱等问题。如不能解决这些问题,也就无从谈起可靠传输。 那么,TCP 是…...

LangChain 11实现思维树Implementing the Tree of Thoughts in LangChain’s Chain
思维之树( Tree of Thoughts ToT)是一个算法,它结合了普林斯顿大学和谷歌DeepMind在本文中提出的大型语言模型(LLMs)和启发式搜索。看起来这个算法正在被实现到谷歌正在开发的多模式生成AI Gemini中。 现在࿰…...
Drools 7 Modify 和对象直接赋值差异
modify代表修改fact,会再次触发符合条件的rule对象直接修改只是java 操作,不会会再次触发符合条件的rule 以下为测试代码-drl部分 package org.drools.learnimport org.drools.learn.ModifyTest.Message;global java.util.List listrule "Stateles…...

vivado产生报告阅读分析21
其他命令选项 • -of_objects <suggestion objects> : 启用特定建议的报告。在此模式下运行时 , report_qor_suggestions 不会生成新建议。此命令可快速执行 , 读取 RQS 文件后 , 此命令可用于查看其中包 含的建议。其…...

9.Docker的虚悬镜像-Dangling Image
1.虚悬镜像的概念 虚悬镜像 (Dangling Image) 指的是仓库名 (镜像名) 和标签 TAG 都是 的镜像。 2.构建本地虚悬镜像 这里我以unbuntu为例来说明。 2.1 编写Dockerfile文件 FROM ubuntu:22.042.2 根据Dockerfile文件构建虚悬镜像 docker build .上面这段命令,…...
02- OpenCV:加载、修改、保存图像
目录 1、加载图像(cv::imread) 2、显示图像 (cv::namedWindos 与cv::imshow) 3、修改图像 (cv::cvtColor) 4、保存图像(cv::imwrite) 5、代码演示 1、加载图像(cv::imread) cv::imread 是 OpenCV 库中用于读取图像文件的函数…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...