如何设置并行度 ——《OceanBase 并行执行》系列 2

并行度(degree of parallelism,简称 DOP),是指在执行过程中所使用的工作线程数量。设计并行执行的初衷在于充分利用多核资源以提升效率。OceanBase 的并行执行框架支持多种设定并行度的方式,既允许用户手动设置,也提供了  Auto DOP 的功能使系统能为用户自动选择合适的并行度。
本篇将重点阐述如何手动设置并行度。

并行执行系列的内容分为七篇博客,本篇是其中的第二篇。

第一篇并行执行概念

2.1 手工指定并行度

可以对一张表指定并行度,使得对这张表的扫描总是使用并行执行。

2.1.1 指定并行度的几种方式

表属性指定并行度

下面的语句分别指定一张主表和一个索引的扫描并行度。

ALTER TABLE table_name PARALLEL 4;
ALTER TABLE table_name ALTER INDEX index_name PARALLEL 2;

如果一个 SQL 中只涉及一张表,当 SQL 中查询了主表时,除了主表所在的 DFO,其余 DFO 也会使用并行度 4 来执行;当 SQL 查询了索引表时,除了索引表所在的 DFO,其余 DFO 也会使用并行度 2 来执行。

如果一个 SQL 中涉及多张表,则会使用 PARALLEL 最大值作为整个计划的 DOP。

PARALLEL HINT 指定并行度

可以通过全局 PARALLEL HINT 来指定整个 SQL 的并行度,也可以通过表级的 PARALLEL HINT 来指定特定表的并行度。当一个 SQL 里给定了多个表的 PARALLEL HINT,那么各个表所在 DFO 的 DOP 由各个表的 Parallel 值决定。如果一个 DFO 里包含多张表,则会取他们的 PARALLEL 最大值作为 DFO 的 DOP。 

OceanBase(TEST@TEST)>create table t1 (c1 int, c2 int);
Query OK, 0 rows affected (0.167 sec)OceanBase(TEST@TEST)>explain select /*+ parallel(3) */ sum(c1) from t1;
+----------------------------------------------------------------------+
| Query Plan                                                           |
+----------------------------------------------------------------------+
| =========================================================            |
| |ID|OPERATOR             |NAME    |EST.ROWS|EST.TIME(us)|            |
| ---------------------------------------------------------            |
| |0 |SCALAR GROUP BY      |        |1       |2           |            |
| |1 | PX COORDINATOR      |        |3       |2           |            |
| |2 |  EXCHANGE OUT DISTR |:EX10000|3       |2           |            |
| |3 |   MERGE GROUP BY    |        |3       |1           |            |
| |4 |    PX BLOCK ITERATOR|        |1       |1           |            |
| |5 |     TABLE SCAN      |T1      |1       |1           |            |
| =========================================================            |
| Outputs & filters:                                                   |
| -------------------------------------                                |
|   0 - output([T_FUN_SUM(T_FUN_SUM(T1.C1))]), filter(nil), rowset=256 |
|       group(nil), agg_func([T_FUN_SUM(T_FUN_SUM(T1.C1))])            |
|   1 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256            |
|   2 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256            |
|       dop=3                                                          |
|   3 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256            |
|       group(nil), agg_func([T_FUN_SUM(T1.C1)])                       |
|   4 - output([T1.C1]), filter(nil), rowset=256                       |
|   5 - output([T1.C1]), filter(nil), rowset=256                       |
|       access([T1.C1]), partitions(p0)                                |
|       is_index_back=false, is_global_index=false,                    |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true    |
+----------------------------------------------------------------------+
24 rows in set (0.002 sec)
OceanBase(TEST@TEST)>create table t1 (c1 int, c2 int);
Query OK, 0 rows affected (0.167 sec)OceanBase(TEST@TEST)>create table t2 (c1 int, c2 int);
Query OK, 0 rows affected (0.150 sec)OceanBase(TEST@TEST)>select /*+ parallel(t1 3) */ * from t1, t2 where t1.c2 = t2.c1;
Empty set (0.041 sec)OceanBase(TEST@TEST)>explain select /*+ parallel(t1 3) */ * from t1, t2 where t1.c2 = t2.c1;
+----------------------------------------------------------------------------------------+
| Query Plan                                                                             |
+----------------------------------------------------------------------------------------+
| =================================================================                      |
| |ID|OPERATOR                     |NAME    |EST.ROWS|EST.TIME(us)|                      |
| -----------------------------------------------------------------                      |
| |0 |PX COORDINATOR               |        |1       |7           |                      |
| |1 | EXCHANGE OUT DISTR          |:EX10002|1       |6           |                      |
| |2 |  HASH JOIN                  |        |1       |5           |                      |
| |3 |   EXCHANGE IN DISTR         |        |1       |2           |                      |
| |4 |    EXCHANGE OUT DISTR (HASH)|:EX10000|1       |2           |                      |
| |5 |     PX BLOCK ITERATOR       |        |1       |1           |                      |
| |6 |      TABLE SCAN             |T1      |1       |1           |                      |
| |7 |   EXCHANGE IN DISTR         |        |1       |4           |                      |
| |8 |    EXCHANGE OUT DISTR (HASH)|:EX10001|1       |4           |                      |
| |9 |     PX PARTITION ITERATOR   |        |1       |2           |                      |
| |10|      TABLE SCAN             |T2      |1       |2           |                      |
| =================================================================                      |
| Outputs & filters:                                                                     |
| -------------------------------------                                                  |
|   0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2, T2.C1, T2.C2)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2, T2.C1, T2.C2)]), filter(nil), rowset=256 |
|       dop=3                                                                            |
|   2 - output([T1.C2], [T2.C1], [T1.C1], [T2.C2]), filter(nil), rowset=256              |
|       equal_conds([T1.C2 = T2.C1]), other_conds(nil)                                   |
|   3 - output([T1.C2], [T1.C1]), filter(nil), rowset=256                                |
|   4 - output([T1.C2], [T1.C1]), filter(nil), rowset=256                                |
|       (#keys=1, [T1.C2]), dop=3                                                        |
|   5 - output([T1.C2], [T1.C1]), filter(nil), rowset=256                                |
|   6 - output([T1.C2], [T1.C1]), filter(nil), rowset=256                                |
|       access([T1.C2], [T1.C1]), partitions(p0)                                         |
|       is_index_back=false, is_global_index=false,                                      |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true                      |
|   7 - output([T2.C1], [T2.C2]), filter(nil), rowset=256                                |
|   8 - output([T2.C1], [T2.C2]), filter(nil), rowset=256                                |
|       (#keys=1, [T2.C1]), dop=1                                                        |
|   9 - output([T2.C1], [T2.C2]), filter(nil), rowset=256                                |
|       force partition granule                                                          |
|  10 - output([T2.C1], [T2.C2]), filter(nil), rowset=256                                |
|       access([T2.C1], [T2.C2]), partitions(p0)                                         |
|       is_index_back=false, is_global_index=false,                                      |
|       range_key([T2.__pk_increment]), range(MIN ; MAX)always true                      |
+----------------------------------------------------------------------------------------+
39 rows in set (0.002 sec)

对于 DML 语句,使用上面的 HINT,只会使得 DML 语句的查询部分走并行,写入部分还是串行。如果希望写入部分也并行,则需要还添加一个 HINT ENABLE_PARALLEL_DML,例如:

insert /*+ parallel(3) enable_parallel_dml */ into t3 select * from t1;

注意:并行 DML 必须指定全局 parallel hint。仅指定表级 parallel hint 无法让写入部分串行。例如,下面的 SQL 不会开启 DML 并行:

insert /*+ parallel(t3 3) enable_parallel_dml */ into t3 select * from t1;

SESSION 上指定并行度

在当前 session 上指定并行度后,session 上的所有查询语句都将以这个并行度执行。需要注意,即使是单行查询的 SQL,也会使用该并行度,可能导致性能下降。

set _force_parallel_query_dop = 3

对于 DML 语句,使用上面的命令,只会使得 DML 语句的查询部分走并行,写入部分还是串行。如果希望写入部分也并行,则需要用下面的命令:

set _force_parallel_dml_dop = 3

2.1.2 并行度优先级

全局 HINT > TABLE HINT > SESSION 并行度 > TABLE DOP

对比全局 HINT 和 TABLE HINT 的优先级。可以看到,有全局 HINT 时,TABLE HINT 不生效。

OceanBase(TEST@TEST)>explain select /*+ parallel(2) parallel(t1 3) */ * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |2           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |2           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=2                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)OceanBase(TEST@TEST)>explain select /*+ parallel(t1 3) */ * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |2           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |1           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=3                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)

对比 session 和 table hint 的优先级。可以看到,使用 table 级的 HINT 时,session 设定的 DOP 不生效。

OceanBase(TEST@TEST)>alter session force parallel query parallel 4;
Query OK, 0 rows affected (0.001 sec)OceanBase(TEST@TEST)>explain select /*+ parallel(t1 3) */ * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |2           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |1           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=3                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)OceanBase(TEST@TEST)>explain select * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |1           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |1           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=4                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)

对比 session 和 table parallel 的优先级。可以看到 table parallel 属性的优先级低于 session 指定 dop 的优先级。

OceanBase(TEST@TEST)>alter table t1 parallel 5;
Query OK, 0 rows affected (0.135 sec)OceanBase(TEST@TEST)>explain select * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |1           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |1           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=5                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)OceanBase(TEST@TEST)>alter session force parallel query parallel 4;
Query OK, 0 rows affected (0.000 sec)OceanBase(TEST@TEST)>explain select * from t1;
+-------------------------------------------------------------------+
| Query Plan                                                        |
+-------------------------------------------------------------------+
| =======================================================           |
| |ID|OPERATOR           |NAME    |EST.ROWS|EST.TIME(us)|           |
| -------------------------------------------------------           |
| |0 |PX COORDINATOR     |        |1       |1           |           |
| |1 | EXCHANGE OUT DISTR|:EX10000|1       |1           |           |
| |2 |  PX BLOCK ITERATOR|        |1       |1           |           |
| |3 |   TABLE SCAN      |T1      |1       |1           |           |
| =======================================================           |
| Outputs & filters:                                                |
| -------------------------------------                             |
|   0 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|   1 - output([INTERNAL_FUNCTION(T1.C1)]), filter(nil), rowset=256 |
|       dop=4                                                       |
|   2 - output([T1.C1]), filter(nil), rowset=256                    |
|   3 - output([T1.C1]), filter(nil), rowset=256                    |
|       access([T1.C1]), partitions(p0)                             |
|       is_index_back=false, is_global_index=false,                 |
|       range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------+
18 rows in set (0.002 sec)

2.1.3 并行度取值

先讲一个简单原则:1. parallel 的设定目的是为了把 CPU 用满。2. parallel 不是越大越好。举个例子:当租户 CPU 为 20 的时:

  • 对于单表简单操作(如单表扫描过滤、单表增删改)parallel 理论值为 20。
  • 对于多表 join 的查询、带全局索引的 PDML,parallel 理论值为 10。
  • 对于一些更加复杂的计划,形态为右深树时,parallel 理论值为 7 左右。

对上面的例子做解释

  • 对于单表操作,只有一个 DFO,可以把 20 个 CPU 全部给这个 DFO 用。
  • 对于多表 join,同一时间会启动 2 个 DFO,形成数据流水线(一个 DFO 是 producer、一个 DFO 是consumer),所有每个 DFO 分 10 个 CPU。
  • 对于更加复杂的右深树计划,我们同一时间会启动 3 个 DFO,此时每个 DFO 大约分 7 个 CPU 可以保证他们都能跑得比较快。

但是,以上只是一般原则,实际操作中还是应该做微调。解释如下:

  • 对于单表操作,只有一个 DFO,可以把 20 个 CPU 全部给这个 DFO 用。
假设这个 DFO 大部分时间是做 IO,那么不妨把并发度设置得比 20 稍高一些,比如 25,这样可以充分利用 CPU
  • 对于多表 join,同一时间会启动 2 个 DFO,形成数据流水线(一个 DFO 是 producer、一个 DFO 是consumer),所有每个 DFO 分 10 个 CPU。
我们实际并不能保证每个 DFO 都能把分给他的 CPU 压满。所以,把并发度适当稍微调整高一些,比如 15 也许能更充分地利用 CPU。 ** 但是,不能无限往上加。把并发度加到 50,根本不会有收益,相反还会增加线程调度开销、框架调度开销。
  • 对于更加复杂的右深树计划,我们同一时间会启动 3 个 DFO,此时每个 DFO 大约分 7 个 CPU 可以保证他们都能跑得比较快。
一个计划里,并不是处处都要启动 3 个 DFO,3 DFO 的情况可能是局部的。大部分时候可能还是同时启动 2 个 DFO。 所以这时候把并发设置为 10 也许比 7 要好。

微调后,当租户 CPU 为 20 的时,一个可能的情况如下:

  • 对于单表简单操作(如单表扫描过滤、单表增删改)parallel 实践值为 30。
  • 对于多表 join 的查询、带全局索引的 PDML,parallel 实践值为 15。
  • 对于一些更加复杂的计划,形态为右深树时,parallel 实践值为 10 ~ 15 左右。

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

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

相关文章

一篇教程搞定Windows系统中的Docker应用安装

文章目录 1. 引言2. “Docker -> WSL -> Windows”的依赖逻辑3. 安装方法3.1 安装WSL3.2 安装Docker Desktop 4. 是否安装成功?初始化一个容器试试。FAQ 1. 引言 Docker是一个用于创建、管理和编排容器的应用。容器是运行在操作系统上的一个应用,…

【Git】Git学习-15:分支简介和基本操作

学习视频链接:【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 git bran…

鸿蒙开发接口Ability框架:【@ohos.ability.particleAbility (particleAbility模块)】

particleAbility模块 particleAbility模块提供了Service类型Ability的能力,包括启动、停止指定的particleAbility,获取dataAbilityHelper,连接、断开当前Ability与指定ServiceAbility等。 说明: 本模块首批接口从API version 7开…

深度学习笔记_10YOLOv8系列自定义数据集实验

1、mydaya.yaml 配置方法 # 这里分别指向你训练、验证、测试的文件地址,只需要指向图片的文件夹即可。但是要注意图片和labels名称要对应 # 训练集、测试集、验证机文件路径,可以是分类好的TXT文件,也可以直接是图片文件夹路径 train: # t…

ue引擎游戏开发笔记(35)——为射击添加轨道,并显示落点

1.需求分析: 我们只添加了开枪特效,事实上并没有实际的效果产生例如弹痕,落点等等。所以逐步实现射击的完整化,先从实现落点开始。 2.操作实现: 1.思路:可以这样理解,每次射击的过程是一次由摄…

百度文库最新AI旋转验证码

上个月发现百度文库最新出了一个验证码,是AI生成的。内容每次可能都不一样,所以给识别造成 了很大困难。传统的比对放松完全失效。 一、介绍 这个是最近才出的最新验证码,内容主要以工厂、建筑、山峰、机器人、汽车、盆栽植物等为主。如下图…

【linux】进程概念|task_struct|getpid|getppid

目录 ​编辑 1.进程的概念 进程的基本概念 进程与程序的主要区别 进程的特征 进程的状态 描述进程—PCB task_struct中的内容 查看进程 1.创建一个进程,运行以下代码 通过系统调用获取进程标示符 getpid()以及getppid() 1.进程的概念 进程的基本概念…

洛谷 P3391:文艺平衡树 ← Splay树模板题

【题目来源】https://www.luogu.com.cn/problem/P3391【题目描述】 您需要写一种数据结构(可参考题目标题),来维护一个有序数列。 其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 1,翻转区间…

深度学习常用优化算法笔记介绍,各种梯度下降法详细介绍

优化算法 mini-batch梯度下降法 当一个数据集其数据量非常大的时候,比如上百万上千万的数据集,如果采用普通的梯度下降法,那么运算速度会非常慢,因为如果使用梯度下降法在每一次迭代的时候,都需要将这整个上百万的数…

航空电子FC节点卡, FC交换机,主要采用LC或MPO光纤接口形式

FC节点卡主要采用LC或MPO光纤接口形式,可以作为4/2个独立端口使用,也可以作为2对/1对冗余端口使用,支持1.0625Gbps、2.125Gbps、4.25Gbps、8.5Gbps通信速率。节点卡完全遵循FC-LS,FC-FS,FC-AE-ASM、FC-AE-1553B等FC光纤…

初始Java篇(JavaSE基础语法)(7)抽象类和接口(上)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:JavaSE 目录 抽象类 抽象类的概念: 抽象类语法 抽象类特性 抽象类的作用 接口 接口的概念: 语法规则 接口…

精通GDBus:Linux IPC的现代C接口

目录标题 1. GDBus介绍2. GDBus的优点3. 安装GDBus4. 使用GDBus连接到D-Bus总线实现D-Bus服务调用D-Bus方法发送和接收信号 5. 总结 在Linux环境下,不同的程序需要通过某种方式进行通信和协同工作。GDBus是GLib库的一部分,提供了一个基于GObject系统的、…

单片机-点亮第一盏灯

原理图 需求:点亮或是熄灭LED 通过控制 P5.3引脚输出高电平时,LED灯就点亮,输出低电平时LED灯就熄灭 1.项目创建 新建项目 配置开发板信息 当前位STC芯片的开发板,选择STC MCU Database 搜素具体芯片型号,进行配置…

[MySQL数据库] Java的JDBC编程(MySQL数据库基础操作完结)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

【北京迅为】《iTOP-3588开发板快速烧写手册》-第8章 TF启动

RK3588是一款低功耗、高性能的处理器,适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用,RK3588支持8K视频编解码,内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

C/C++ 初级球球大作战练手

效果演示&#xff1a; https://live.csdn.net/v/385490 游戏初始化 #include <stdbool.h> #include<stdio.h> #include<stdlib.h> #include<time.h> #include<graphics.h> #include <algorithm> #include<math.h> #include<mmsy…

java多线程编码应用1——java多线程CompletableFuture使用技巧

在实际项目开发过程中&#xff0c;大部分程序的执行顺序都是按照代码编写的先后顺序&#xff0c;依次从上往下挨个执行的&#xff0c;但是对于统计或者批量操作数据时&#xff0c;是否有更好的方案呢&#xff1f;这时候就可以考虑使用多线程编程&#xff0c;异步并行执行多个任…

【MATLAB画图】如何绘制图像坐标系

首先我们需要图像坐标轴的原点在左上角&#xff1a; set(gca,ydir,reverse,xaxislocation,top); 然后我们需要坐标轴上加上箭头 quiver(0, 0, 0, 520); % 在(x1, y1)处绘制一个箭头&#xff0c;其方向和长度由(dx, dy)确定 quiver(0, 0, 700, 0); % 在(x1, y1)处绘制一个箭头…

英语新概念2-回译法-lesson13

The Greenwood Boys 绿林少年是一组流行歌手们。现在他们正在参观城市里的所有公园&#xff0c;他们明天就要到这。他们将坐火车到并且大多数小镇上的年轻人将要欢迎他们&#xff0c;明天晚上他们将要在工人俱乐部唱歌。绿林少年将在这待五天&#xff0c;在这期间&#xff0c;…

flowable一对并发网关跳转的分析

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…