OceanBase中左外连接和反连接的经验分享
本文作者:张瑞远,曾从事银行、证券数仓设计、开发、优化类工作,现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作。 持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得的专业技能与认证包括 OceanBase OBCE、Oracle OCP 11g、OracleOCM 11g 、MySQL OCP 5.7 等。
背景:
近期处理了一些关于not exsts导致的性能sql,这里将这些经验整理并分享给大家。
验证案例:
sql文本如下,由于篇幅限制,并且对于理解本次分享的核心内容来说,建表语句及具体数据量信息并非必需,因此我在此省略了相关细节。
select count(1)from tttt.mmmmm_sssssale twhere t.sssss not in ('e111', 'ddddda')and t.stats = '1'and t.parean is nulland t.city = 2208AND (t.cusystatus = 'FFFFGGGGG')AND (T.ORGGGGGGNEL is null or T.ORGGGGGGNEL != 'infonow')AND NOT EXISTS (SELECT 1FROM tttt.TTTT_OWN_C TOWWHERE T.PID = TOW.OIDAND TOW.CT_ID = T.cityAND TOW.OODDD_sTS IN(SELECT DDDCFROM tttt.CTM_GMWHERE GPID = 'OtherThing'AND stats = '1')) and to_char(createdate,'yyyymmdd') between 20150101 and 202301211;
该sql我们看下执行计划和执行时间
+----------+
| COUNT(1) |
+----------+
| 29487 |
+----------+
1 row in set (43.77 sec)*************************** 1. row ***************************
Query Plan: ===========================================================================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
-------------------------------------------------------------------------------------------
|0 |SCALAR GROUP BY | |1 |165892|
|1 | NESTED-LOOP ANTI JOIN | |858 |165860|
|2 | TABLE SCAN |T |1329 |40619 |
|3 | PX COORDINATOR | |1 |94 |
|4 | EXCHANGE OUT DISTR |:EX10001 |1 |94 |
|5 | SUBPLAN SCAN |VIEW2 |1 |94 |
|6 | NESTED-LOOP JOIN | |1 |94 |
|7 | EXCHANGE IN DISTR | |1 |92 |
|8 | EXCHANGE OUT DISTR (BC2HOST)|:EX10000 |1 |92 |
|9 | TABLE SCAN |TOW(IDX_TTTT_OWN_C_ORDERID) |1 |92 |
|10| TABLE SCAN |SD_CTM_GM(PK_SD_CTM_GM) |1 |32 |
===========================================================================================Outputs & filters:
-------------------------------------0 - output([T_FUN_COUNT(*)(0x7f4fe8fdbcb0)]), filter(nil), group(nil), agg_func([T_FUN_COUNT(*)(0x7f4fe8fdbcb0)])1 - output([remove_const(1)(0x7f4af5473fc0)]), filter(nil), conds(nil), nl_params_([T.PID(0x7f4fe8f81610)]), batch_join=false2 - output([T.PID(0x7f4fe8f81610)]), filter([T.city(0x7f4fe8f34b00) = 2208(0x7f4fe8f343e0)], [cast(cast(TO_CHAR(T.CREATEDATE(0x7f4fe8fd6170), ?)(0x7f4fe8fd2470), VARCHAR2(256 BYTE))(0x7f4fe8fd7100), NUMBER(-1, -85))(0x7f4fe8fd7a90) >= 20150101(0x7f4fe8fd4c10)], [cast(cast(TO_CHAR(T.CREATEDATE(0x7f4fe8fd6170), ?)(0x7f4fe8fd3ad0), VARCHAR2(256 BYTE))(0x7f4fe8fd93a0), NUMBER(-1, -85))(0x7f4fe8fd9d30) <= 202301211(0x7f4fe8fd52f0)], [(T_OP_IS, T.ORGGGGGGNEL(0x7f4fe8f383b0), NULL, 0)(0x7f4fe8f36ca0) OR T.ORGGGGGGNEL(0x7f4fe8f383b0) != ?(0x7f4fe8f37bf0)(0x7f4fe8f36020)], [(T_OP_NOT_IN, T.sssss(0x7f4fe8f31520), (?, ?)(0x7f4fe8f30860))(0x7f4fe8f2fe70)], [(T_OP_IS, T.parean(0x7f4fe8f33a00), NULL, 0)(0x7f4fe8f33030)], [T.stats(0x7f4fe8f32680) = ?(0x7f4fe8f31f60)], [T.cusystatus(0x7f4fe8f35c10) = ?(0x7f4fe8f354f0)]), access([T.sssss(0x7f4fe8f31520)], [T.stats(0x7f4fe8f32680)], [T.parean(0x7f4fe8f33a00)], [T.city(0x7f4fe8f34b00)], [T.cusystatus(0x7f4fe8f35c10)], [T.ORGGGGGGNEL(0x7f4fe8f383b0)], [T.PID(0x7f4fe8f81610)], [T.CREATEDATE(0x7f4fe8fd6170)]), partitions(p0), is_index_back=false, filter_before_indexback[false,false,false,false,false,false,false,false], range_key([T.__pk_increment(0x7f4fe903ae10)]), range(MIN ; MAX)always true3 - output([remove_const(1)(0x7f4af5474810)]), filter(nil)4 - output([remove_const(1)(0x7f4af5475060)]), filter(nil), is_single, dop=15 - output([remove_const(1)(0x7f4af54758b0)]), filter(nil), access([VIEW2.TOW.OID(0x7f4fe8fef420)])6 - output([TOW.OID(0x7f4af53c1210)]), filter(nil), conds(nil), nl_params_([TOW.OODDD_sTS(0x7f4af53c17f0)]), batch_join=true7 - output([TOW.OID(0x7f4af53c1210)], [TOW.OODDD_sTS(0x7f4af53c17f0)]), filter(nil)8 - output([TOW.OID(0x7f4af53c1210)], [TOW.OODDD_sTS(0x7f4af53c17f0)]), filter(nil), is_single, dop=19 - output([TOW.OID(0x7f4af53c1210)], [TOW.OODDD_sTS(0x7f4af53c17f0)]), filter([TOW.CT_ID(0x7f4af53c1500) = 2208(0x7f4af53c23b0)]), access([TOW.OID(0x7f4af53c1210)], [TOW.CT_ID(0x7f4af53c1500)], [TOW.OODDD_sTS(0x7f4af53c17f0)]), partitions(p0), is_index_back=true, filter_before_indexback[true], range_key([TOW.OID(0x7f4af53c1210)], [TOW.WORK_STATION(0x7f4af53f1de0)], [TOW.CT_ID(0x7f4af53c1500)], [TOW.__pk_increment(0x7f4af53ec1d0)]), range(MIN,MIN,MIN,MIN ; MAX,MAX,MAX,MAX)always true, range_cond([? = TOW.OID(0x7f4af53c1210)(0x7f4af53c47c0)])10 - output([remove_const(1)(0x7f4af5476100)]), filter([SD_CTM_GM.stats(0x7f4af53c1dd0) = ?(0x7f4af53c2ea0)]), access([SD_CTM_GM.stats(0x7f4af53c1dd0)]), partitions(p0), is_index_back=true, filter_before_indexback[false], range_key([SD_CTM_GM.DDDC(0x7f4af53c20c0)], [SD_CTM_GM.GPID(0x7f4af53c1ae0)], [SD_CTM_GM.shadow_pk_0(0x7f4af5410640)]), range(MIN ; MAX), range_cond([SD_CTM_GM.GPID(0x7f4af53c1ae0) = ?(0x7f4af53c3f60)], [? = SD_CTM_GM.DDDC(0x7f4af53c20c0)(0x7f4af5423680)])
可以看到执行时间43s正常这个效率,在线业务的话很难接受,因为该sql并不复杂,执行计划没有太大的问题,走了nl anti join。
后来我尝试改写掉not exist
obclient> select count(1)-> from tttt.mmmmm_sssssale t-> left join tttt.TTTT_OWN_C TOW -> on T.PID = TOW.OID-> AND TOW.CT_ID = T.city-> AND TOW.OODDD_sTS IN-> (SELECT DDDC-> FROM tttt.CTM_GM-> WHERE GPID = 'OtherThing'-> AND stats = '1')-> where t.sssss not in ('e111', 'ddddda')-> and t.stats = '1'-> and t.parean is null-> and t.city = 2208-> AND (t.cusystatus = 'FFFFGGGGG')-> AND (T.ORGGGGGGNEL is null or T.ORGGGGGGNEL != 'infonow')-> and to_char(createdate,'yyyymmdd') between 20150101 and 202301211-> and TOW.CT_ID is null and TOW.OID is null ;
+----------+
| COUNT(1) |
+----------+
| 29487 |
+----------+
1 row in set (1.08 sec)Query Plan: ===========================================================================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
-------------------------------------------------------------------------------------------
|0 |SCALAR GROUP BY | |1 |163357|
|1 | NESTED-LOOP OUTER JOIN | |858 |163324|
|2 | TABLE SCAN |T |1329 |40619 |
|3 | PX COORDINATOR | |1 |92 |
|4 | EXCHANGE OUT DISTR |:EX10001 |1 |92 |
|5 | SUBPLAN SCAN |VIEW1 |1 |92 |
|6 | NESTED-LOOP JOIN | |1 |92 |
|7 | EXCHANGE IN DISTR | |1 |92 |
|8 | EXCHANGE OUT DISTR (BC2HOST)|:EX10000 |1 |92 |
|9 | TABLE SCAN |TOW(IDX_TTTT_OWN_C_ORDERID) |1 |92 |
|10| TABLE SCAN |SD_CTM_GM(PK_SD_CTM_GM) |1 |32 |
===========================================================================================Outputs & filters:
-------------------------------------0 - output([T_FUN_COUNT(*)(0x7f4fe8f96f80)]), filter(nil), group(nil), agg_func([T_FUN_COUNT(*)(0x7f4fe8f96f80)])1 - output([remove_const(1)(0x7f68c967e220)]), filter([(T_OP_IS, VIEW1.TOW.CT_ID(0x7f4fe8fec060), NULL, 0)(0x7f4fe8f953d0)], [(T_OP_IS, VIEW1.TOW.OID(0x7f4fe8febd70), NULL, 0)(0x7f4fe8f96480)]), conds(nil), nl_params_([T.PID(0x7f4fe8f31660)], [T.city(0x7f4fe8f32d90)]), batch_join=false, px_batch_rescan=true2 - output([T.PID(0x7f4fe8f31660)], [T.city(0x7f4fe8f32d90)]), filter([T.city(0x7f4fe8f32d90) = 2208(0x7f4fe8f864a0)], [cast(cast(TO_CHAR(T.CREATEDATE(0x7f4fe8f8f2e0), ?)(0x7f4fe8f8b5e0), VARCHAR2(256 BYTE))(0x7f4fe8f90270), NUMBER(-1, -85))(0x7f4fe8f90c00) >= 20150101(0x7f4fe8f8dd80)], [cast(cast(TO_CHAR(T.CREATEDATE(0x7f4fe8f8f2e0), ?)(0x7f4fe8f8cc40), VARCHAR2(256 BYTE))(0x7f4fe8f92510), NUMBER(-1, -85))(0x7f4fe8f92ea0) <= 202301211(0x7f4fe8f8e460)], [(T_OP_IS, T.ORGGGGGGNEL(0x7f4fe8f8a180), NULL, 0)(0x7f4fe8f88a70) OR T.ORGGGGGGNEL(0x7f4fe8f8a180) != ?(0x7f4fe8f899c0)(0x7f4fe8f87df0)], [(T_OP_NOT_IN, T.sssss(0x7f4fe8f835e0), (?, ?)(0x7f4fe8f82920))(0x7f4fe8f81f30)], [(T_OP_IS, T.parean(0x7f4fe8f85ac0), NULL, 0)(0x7f4fe8f850f0)], [T.stats(0x7f4fe8f84740) = ?(0x7f4fe8f84020)], [T.cusystatus(0x7f4fe8f879e0) = ?(0x7f4fe8f872c0)]), access([T.PID(0x7f4fe8f31660)], [T.city(0x7f4fe8f32d90)], [T.sssss(0x7f4fe8f835e0)], [T.stats(0x7f4fe8f84740)], [T.parean(0x7f4fe8f85ac0)], [T.cusystatus(0x7f4fe8f879e0)], [T.ORGGGGGGNEL(0x7f4fe8f8a180)], [T.CREATEDATE(0x7f4fe8f8f2e0)]), partitions(p0), is_index_back=false, filter_before_indexback[false,false,false,false,false,false,false,false], range_key([T.__pk_increment(0x7f4fe90416b0)]), range(MIN ; MAX)always true3 - output([VIEW1.TOW.OID(0x7f4fe8febd70)], [VIEW1.TOW.CT_ID(0x7f4fe8fec060)]), filter(nil)4 - output([VIEW1.TOW.OID(0x7f4fe8febd70)], [VIEW1.TOW.CT_ID(0x7f4fe8fec060)]), filter(nil), is_single, dop=15 - output([VIEW1.TOW.OID(0x7f4fe8febd70)], [VIEW1.TOW.CT_ID(0x7f4fe8fec060)]), filter(nil), access([VIEW1.TOW.OID(0x7f4fe8febd70)], [VIEW1.TOW.CT_ID(0x7f4fe8fec060)])6 - output([TOW.OID(0x7f68c95c53a0)], [TOW.CT_ID(0x7f68c95c5690)]), filter(nil), conds(nil), nl_params_([TOW.OODDD_sTS(0x7f68c95c5980)]), batch_join=true7 - output([TOW.OID(0x7f68c95c53a0)], [TOW.CT_ID(0x7f68c95c5690)], [TOW.OODDD_sTS(0x7f68c95c5980)]), filter(nil)8 - output([TOW.OID(0x7f68c95c53a0)], [TOW.CT_ID(0x7f68c95c5690)], [TOW.OODDD_sTS(0x7f68c95c5980)]), filter(nil), is_single, dop=19 - output([TOW.OID(0x7f68c95c53a0)], [TOW.CT_ID(0x7f68c95c5690)], [TOW.OODDD_sTS(0x7f68c95c5980)]), filter([TOW.CT_ID(0x7f68c95c5690) = 2208(0x7f68c95c6540)], [TOW.CT_ID(0x7f68c95c5690) = ?(0x7f68c95c9230)]), access([TOW.OID(0x7f68c95c53a0)], [TOW.CT_ID(0x7f68c95c5690)], [TOW.OODDD_sTS(0x7f68c95c5980)]), partitions(p0), is_index_back=true, filter_before_indexback[true,true], range_key([TOW.OID(0x7f68c95c53a0)], [TOW.WORK_STATION(0x7f68c95f8780)], [TOW.CT_ID(0x7f68c95c5690)], [TOW.__pk_increment(0x7f68c95f0c50)]), range(MIN,MIN,MIN,MIN ; MAX,MAX,MAX,MAX)always true, range_cond([? = TOW.OID(0x7f68c95c53a0)(0x7f68c95c8950)])10 - output([remove_const(1)(0x7f68c967ea70)]), filter([SD_CTM_GM.stats(0x7f68c95c5f60) = ?(0x7f68c95c7030)]), access([SD_CTM_GM.stats(0x7f68c95c5f60)]), partitions(p0), is_index_back=true, filter_before_indexback[false], range_key([SD_CTM_GM.DDDC(0x7f68c95c6250)], [SD_CTM_GM.GPID(0x7f68c95c5c70)], [SD_CTM_GM.shadow_pk_0(0x7f68c961ab30)]), range(MIN ; MAX), range_cond([SD_CTM_GM.GPID(0x7f68c95c5c70) = ?(0x7f68c95c80f0)], [? = SD_CTM_GM.DDDC(0x7f68c95c6250)(0x7f68c962db70)])
这时候可以看到效率提升到了1s,提升了40多倍,那么原因在哪,从上图可以看到执行计划基本一样,唯一的区别是连接方式。
从ESTED-LOOP ANTI JOIN反连接转化成了NESTED-LOOP OUTER JOIN左外连接,正常理解这两种连接方式效率差距不应该这么大,从Outputs & filters信息中可以看到左外连接用了一个px_batch_rescan=true算子。
我们可以从源码的join/nl这块看到px_batch_rescan的一些信息,可以对nl做一些优化,避免扫描多余的数据。
if (OB_SUCC(ret)) {// 当nlj条件下推做分布式rescan, 开启px batch rescanObNestedLoopJoinSpec &nlj = static_cast<ObNestedLoopJoinSpec &>(spec);if (op.enable_px_batch_rescan()) {nlj.enable_px_batch_rescan_ = true;nlj.group_size_ = PX_RESCAN_BATCH_ROW_COUNT;} else {nlj.enable_px_batch_rescan_ = false;}}if (OB_SUCC(ret) && PHY_NESTED_LOOP_JOIN == spec.type_) {ObNestedLoopJoinSpec &nlj = static_cast<ObNestedLoopJoinSpec &>(spec);bool use_batch_nlj = op.can_use_batch_nlj();if (use_batch_nlj) {nlj.group_rescan_ = use_batch_nlj;}
// 左边每一行出来后,去通知右侧 GI 实施 part id 过滤,避免 PKEY NLJ 场景下扫不必要分区
if (OB_SUCC(ret) && !get_spec().enable_px_batch_rescan_ && get_spec().enable_gi_partition_pruning_) {ObDatum *datum = nullptr;if (OB_FAIL(get_spec().gi_partition_id_expr_->eval(eval_ctx_, datum))) {LOG_WARN("fail eval value", K(ret));} else {// NOTE: 如果右侧对应多张表,这里的逻辑也没有问题// 如 A REPART TO NLJ (B JOIN C) 的场景// 此时 GI 在 B 和 C 的上面int64_t part_id = datum->get_int();ctx_.get_gi_pruning_info().set_part_id(part_id);}
而外连接也是在该块代码里的
// outer joinif (OB_SUCC(ret)) {if (match_right_batch_end_ && no_match_row_found_ && need_left_join()) {need_output_row_ = true;}}
但是反连接是被查询改写之后的算子,该代码在rewrite的transform模块,并不能用到px_batch_rescan的算子优化。
结论:
虽然一些条件下,ob会把反连接和半连接自动改写为外连接和内连接,但是条件相对苛刻(感兴趣的同学可以翻下代码的ob_transform_join_elimination.h的介绍),现阶段遇到这类sql,可能更多的还要依赖我们开发和维护人员去手动去优化。
行之所向,莫问远方。
相关文章:
OceanBase中左外连接和反连接的经验分享
本文作者:张瑞远,曾从事银行、证券数仓设计、开发、优化类工作,现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作。 持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得的专业技能与认证…...

如何提升公众号搜索量?分享内部运营的5步优化技术!
最近一直有自媒体同行朋友在写关于公众号的内容,很多都说公众号现在没得玩了。其实,在运营自媒体上面,思维不通,技术不到位,哪个平台都不适合你玩。 想要在自媒体上面运营变现,一定不要先点击广告变现&…...
【2024】根据系统平均负载情况排查隐患
查看系统负载情况的时候可以使用top和uptime命令。 其中top是一个比较综合的命令,如果我们只需要查看负载情况,可以直接使用uptime命令即可。 uptime命令是一个查看系统运行时间和负载情况的命令,分为四个部分: 系统当前时间系统运行时间当前登录用户数系统平均负载:分别…...

分类任务中的评估指标:Accuracy、Precision、Recall、F1
概念理解 T P TP TP、 T N TN TN、 F P FP FP、 F N FN FN精度/正确率( A c c u r a c y Accuracy Accuracy) 二分类查准率 P r e c i s i o n Precision Precision,查全率 R e c a l l Recall Recall 和 F 1 − s c o r e F1-score F1−s…...
android 音视频基础知识--个人笔记
avi,mkv封装格式数据------》音频流,视频流//字母流(国外会分开) ----〉解封装,解复用打开封装格式 -----》视频压缩数据---压缩H264,H265 -------〉视频解码 ----》原始数据YUV -----〉音频压缩数据---…...
信息工程大学第五届超越杯程序设计竞赛(同步赛)题解
比赛传送门 博客园传送门 c 模板框架 #pragma GCC optimize(3,"Ofast","inline") #include<bits/stdc.h> #define rep(i,a,b) for (int ia;i<b;i) #define per(i,a,b) for (int ia;i>b;--i) #define se second #define fi first #define e…...
Python:文件读写
一、TXT文件读写 Python中用open()函数来读写文本文件,返回文件对象,以下是函数语法。 open(<name>, <mode>, <buffering>,<encoding)name:文件名。 mode:打开文件模式。 buffering:设…...
10.windows ubuntu 组装软件:spades,megahit
Spades 是一种用于组装测序数据的软件,特别适用于处理 Illumina 测序平台产生的数据。它的全称是 "St. Petersburg genome assembler",是一款广泛使用的基因组组装工具。 第一种:wget https://cab.spbu.ru/files/release3.15.3/S…...

K8S之Secret的介绍和使用
Secret Secret的介绍Secret的使用通过环境变量引入Secret通过volume挂载Secret Secret的介绍 Secret是一种保护敏感数据的资源对象。例如:密码、token、秘钥等,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使…...

git下载安装教程
git下载地址 有一个镜像的网站可以提供下载: https://registry.npmmirror.com/binary.html?pathgit-for-windows/图太多不截了哈哈,一直next即可。...

《剑指 Offer》专项突破版 - 面试题 98、99 和 100 : 和动态规划相关的矩阵路径问题(C++ 实现)
目录 前言 面试题 98 : 路径的数目 面试题 99 : 最小路径之和 面试题 100 : 三角形中最小路径之和 前言 矩阵路径是一类常见的可以用动态规划来解决的问题。这类问题通常输入的是一个二维的格子,一个机器人按照一定的规则从格子的某个位置走到另一个位置&#…...
KY145 EXCEL排序(用Java实现)
描述 Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。 对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C…...

属性选择器
1.[title]{background:yellow;}:所有带title标签设置成黄色 2.div[class]{background:yellow;}:所有div中带class标签设置成黄色 3.div[classbox1]{border:1px solid blue; }:div中包含class并且classbox1的设置成蓝边框 4. class…...

软考 - 系统架构设计师 - 关系模型的完整性规则
前言 关系模型的完整性规则是一组用于确保关系数据库中数据的完整性和一致性的规则。这些规则定义了在关系数据库中如何存储、更新和查询数据,以保证数据的准确性和一致性。 详情 关系模型的完整性规则主要包括以下三类: 实体完整性规则 这是确保每个…...
写了几个难一点的sql
写了几个难一点的sql SELECT bn.id AS book_node_id, t.version_id, bn.textbook_id, s.id AS subject_id, s.stage_id, COUNT( CASE WHEN d.document_type_id 1 AND d.scope IS NULL AND p.document_id IS NOT NULL THEN 1 END ) AS type_1_count, COUNT( CASEWHEN d.docume…...

【JDK常用的API】包装类
🍬 博主介绍👨🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …...
Android Q(10)黑暗模式适配的实现
一、引言 随着 AndroidQ(10)的发布,黑暗模式成为了系统级别的特性。为了满足用户在不同环境下的使用需求,应用程序需要及时进行黑暗模式的适配。本文将详细介绍如何在 AndroidQ(10)上实现黑暗模式的适配&a…...

【git】git使用手册
目录 一 初始化 1.1 账号配置 1.2 ssh生成 1.2.1 配置ssh 1.2.2 测试SSH 1.3 初始化本地仓库并关联远程仓库 二 使用 2.1 上传 2.2 拉取 三 问题 3.1 关联失败 一 初始化 git的安装很简单,下载后大部分进行下一步完成即可----->地址: git工具下载 1.1 账号配置…...
unity中判断方向 用 KeyVertical ,KeyHorizontal 判断ui物体的 方向
float KeyVertical Input.GetAxis("Vertical"); float KeyHorizontal Input.GetAxis("Horizontal"); // 假设 UI 物体在竖直方向上为 Y 轴,水平方向上为 X 轴 Vector2 direction new Vector2(KeyHorizontal, KeyVertical); if (direction…...
前端a4纸尺寸转像素尺寸
前端必备工具推荐网站(免费图床、API和ChatAI等实用工具): http://luckycola.com.cn/ 一、a4纸张有多大 A4纸的尺寸是210mm297mm,也就是21.0cm29.7cm, A4纸尺寸转屏幕像素尺寸和屏幕分辨率有关,首先1英寸2.54cm, 如果屏幕DPI分辨率为72像素/英寸,换算一下ÿ…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...