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,可能更多的还要依赖我们开发和维护人员去手动去优化。

行之所向,莫问远方。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/783781.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp开发小程序生成和扫描二维码

uniapp中生成二维码和扫码二维码 1.首先建立一个可运行的小程序 2. 安装uqrcodejs 安装了cnpm后,使用cnpm命令也行 npm install uqrcodejs 3. 安装成功后,在这里就能看到了 4. 代码 <template><button @click="ShowTwoCodeClick">生成二维码</…

linux内核驱动在本机编译与交叉编译

linux内核驱动具有通用性&#xff0c;可以在内核驱动中跟随系统一同编译&#xff0c;也可以通过模块形式编译。 这里介绍写在模块形式编译时本机编译与交叉编译的配置。 源代码是一样的&#xff0c;只需要修改makefile文件即可。 这里以一个RK3588的驱动为例。 1. 本机编译…

MyBatis细节注意

1.参数占位符:${}和#{} #{}&#xff1a;占位符会将传入的值安全地转义&#xff0c;防止SQL注入攻击&#xff0c;它会在预编译阶段将占位符替换为一个问号 ?&#xff0c;然后通过PreparedStatement设置参数值&#xff0c;从而确保安全性。适用于实际参数值作为参数传递给SQL语句…

Java 图形用户界面

JFrame JFrame是Java中用于创建图形用户界面(GUI)的顶级容器类。 JFrame类是Swing库中的一个关键组件&#xff0c;它代表一个窗口&#xff0c;可以向其中添加各种GUI组件来构建应用程序的用户界面。以下是JFrame的一些基本用法和特性&#xff1a; 创建JFrame对象&#xff1a…

240330-大模型资源-使用教程-部署方式-部分笔记

A. 大模型资源 Models - Hugging FaceHF-Mirror - Huggingface 镜像站模型库首页 魔搭社区 B. 使用教程 HuggingFace HuggingFace 10分钟快速入门&#xff08;一&#xff09;&#xff0c;利用Transformers&#xff0c;Pipeline探索AI。_哔哩哔哩_bilibiliHuggingFace快速入…

ChatGPT引领学术风潮:写作技巧与实践

ChatGPT无限次数:点击直达 ChatGPT引领学术风潮&#xff1a;写作技巧与实践 引言 在当今信息爆炸的时代&#xff0c;各行各业对于内容创作的需求日益增长&#xff0c;人们追求更高效、更优质的写作工具。ChatGPT作为一款具有自我学习和生成文本能力的先进AI技术&#xff0c;成…

【计算机视觉】四篇基于Gaussian Splatting的SLAM论文对比

本文对比四篇论文&#xff1a; [1] Gaussian Splatting SLAM [2] SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM [3] Gaussian-SLAM: Photo-realistic Dense SLAM with Gaussian Splatting [4] GS-SLAM: Dense Visual SLAM with 3D Gaussian Splatting …

汇编语言——用INT 21H 的A号功能,输入一个字符串存放在内存,倒序输出

用INT 21H 的A号功能&#xff0c;输入一个字符串“Hello, world!”&#xff0c;存放在内存&#xff0c;然 后倒序输出。 在DOS中断中&#xff0c;INT 21H是一个常用的系统功能调用中断&#xff0c;它提供了多种功能&#xff0c;其中A号功能用于字符串的输入。 在使用这个功能时…

高级排序算法:归并排序(优化版)

题目描述 leecode第912题&#xff1a;排序数组&#xff1a; 给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 示例 1&#xff1a; 输入&#xff1a;nums [5,2,3,1] 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;nums [5,1,1,2,0,0] 输出&…

【PSINS工具箱】基于工具箱,自己设计的轨迹,并生成IMU数据和三维视图(完整代码)

完整代码 在有工具箱的情况下&#xff0c;直接运行代码&#xff0c;即可 % 基于PSINS工具箱的三维轨迹生成、三维图像绘制与IMU数据生成 % date:2024-2-13 % Evand&#xff08;evandworldqq.com&#xff09; % Ver1 clear;clc;close all; glvs ts 0.1; % sampling int…

RuntimeError: CUDA error: an illegal memory access was encountered

前言 我在跑深度学习模型。其中卷积用CUDA写的。数据集是cifar10。在运行了1个epoch后&#xff0c;就报错&#xff1a;RuntimeError: CUDA error: an illegal memory access was encountered。这个错误是在调用loss.backward()方法时出现的。 在网上看了很多方法&#xff0c;有…

linux自定义命令

文章目录 1、自定义命令介绍2、自定义命令步骤 (centos7)2.1 新建隐藏目录存放自定义命令脚本文件2.2 将新建的目录配置环境变量2.3 取别名的方式简化已有命令2.4 编写自定义命令脚本 1、自定义命令介绍 不管是linux系统还是windows系统都支持自定义命令&#xff0c;windows端…

学习 C++ 一定要搭配 Linux 吗?

学习C并不一定非要搭配Linux&#xff0c;但使用Linux环境进行学习和开发确实有其独特的优势&#xff0c;尤其对于深入理解和实践某些高级主题及特定领域的开发工作。以下是关于是否需要搭配Linux学习C的详细分析&#xff1a; 为了帮助您更好地入门并深入掌握C&#xff0c;我们精…

PLC的大脑和心脏——CPU及西门子S7-1200CPU分类、CPU型号及端子接线图示例

CPU不断地采集输入信号&#xff0c;执行用户程序&#xff0c;刷新系统的输出。 根据供电方式和输入/输出方式的不同&#xff0c;西门子S7-1200 CPU分为3类&#xff0c;如下图1。 图1 CPU的分类 第1对字母&#xff0c;表示CPU的供电方式&#xff0c;AC&#xff08;Alternating…

Python实现的网页爬虫示例

当然可以。以下是一个使用Python实现的基础网页爬虫示例。这个示例将使用requests库来发送HTTP请求&#xff0c;并使用BeautifulSoup库来解析HTML文档。如果你还没有安装这两个库&#xff0c;请先使用pip进行安装&#xff1a; pip install requests beautifulsoup4接下来是网页…

代码随想录第25天|216.组合总和III 17.电话号码的字母组合

216.组合总和III 216. 组合总和 III - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 和组合问题有啥区别&#xff1f;回溯算法如何剪枝&#xff1f;| LeetCode&#xff1a;216.组合总和III_哔哩哔哩_bilibili 找出所有相加之和为 n 的 k 个数的组…

【KingSCADA】播放语音

1.函数介绍 PlaySound(string strWaveFileName, int nMode);下面是官方帮助文档中的解释&#xff1a; 2.生成语音文件 3.使用脚本播放音频文件 将音频文件存放在工程目录下面&#xff0c;我存放在了…\Resources\文件夹下&#xff1a; 我简单的写了一个定时1分钟播放一次语…

Fluent循环流动案例(模拟循环泵,含换热、散热、VOF、UDF)

在此特意记录下循环通道的fluent思路和参数设置 该案例中&#xff0c;主要关注的是催化剂域的温度变化情况&#xff0c;因此需要监控的是温度的变化曲线&#xff0c;关于泵如何进行模拟&#xff0c;这里有两种思路&#xff0c;一种是用风扇代替泵&#xff0c;优点是整个流体域基…

HarmonyOS ArkTS 骨架屏加载显示(二十五)

目录 前言1、骨架屏代码显示2、代码中引用3、效果图展示 前言 所谓骨架屏&#xff0c;就是在页面进行耗时加载时&#xff0c;先展示的等待 UI, 以告知用户程序目前正在运行&#xff0c;稍等即可。 等待的UI大部分是 loading 转圈的弹窗&#xff0c;有的是自己风格的小动画。其实…

JS - const 关键字声明的变量并不是常量

// 1. 赋值给一个变量 const declare function (x) { return x * x; }; 读到这部分时‘ 疑惑注释为什么会是说 把这个函数表达式赋值给一个变量 在 JavaScript 中&#xff0c;使用 const 关键字声明的变量并不是常量&#xff08;immutable&#xff09;&#xff0c;而是常量引用…