MySQL-进阶篇-SQL优化(插入数据优化、主键优化、order by优化、group by优化、limit优化、count优化、update优化)

news2024/11/24 11:11:17

文章目录

  • 1. 插入数据优化
    • 1.1 使用批量插入
    • 1.2 批量插入数据时手动提交事务
    • 1.3 按主键的顺序插入
    • 1.4 大批量插入数据时使用 load 指令
  • 2. 主键优化
    • 2.1 数据组织方式
    • 2.2 页分裂
    • 2.3 页合并
    • 2.4 主键的设计原则
      • 2.4.1 降低主键的长度
      • 2.4.2 使用 AUTO_INCREMENT 自增主键
      • 2.4.3 尽量不要使用 UUID 或者是其他自然主键(如身份证号)做主键
      • 2.4.4 选择不受业务操作影响的字段作为主键
  • 3. order by 优化
    • 3.1 测试
    • 3.2 总结
  • 4. group by 优化
    • 4.1 测试
    • 4.2 总结
  • 5. limit 优化
  • 6. count 优化
  • 7. update 优化(防止行锁升级为表锁)
    • 7.1 测试
    • 7.2 总结

阅读本文前,建议先阅读另一篇博文:MySQL-进阶篇-索引(索引概述、索引的结构、索引的分类、索引的语法、性能分析工具、索引的使用规则、索引的设计原则)

1. 插入数据优化

1.1 使用批量插入

如果要往表中批量插入数据,不要执行多条 insert 语句,因为每执行一次 insert 语句都需要与数据库建立连接,进行网络传输,性能是比较低的

批量插入数据时建议使用批量插入,MySQL 批量插入的语法如下

INSERT INTO 表名 (1,2,3, ..., 列N)
VALUES (1_1,1_2,1_3, ...,1_N),
       (2_1,2_2,2_3, ...,2_N),
       ...
       (值M_1, 值M_2, 值M_3, ..., 值M_N);

但是一次性插入的数据不建议超过 1000 条,原因主要有以下几点:

  1. 性能问题:大量数据的插入可能会导致数据库的性能下降。长时间的插入操作可能会锁定表,影响其他数据库操作的性能
  2. 内存消耗:当插入大量数据时,MySQL可能会消耗大量内存来处理这些数据,这可能会导致服务器内存不足
  3. 错误处理:如果在插入过程中发生错误(如数据格式不正确、违反约束等),处理大量数据的错误会更加复杂。如果错误导致事务回滚,那么所有已经插入的数据都需要重新插入
  4. 锁定时间:批量插入可能会导致表锁定较长时间,这会阻塞其他尝试写入该表的操作

那如果要插入几万条数据呢?我们可以将数据分成多个部分,使用多条 insert 语句插入

1.2 批量插入数据时手动提交事务

在 MySQL 中,事务默认是自动提交的,每执行一条 insert 语句,就会提交一次事务,如果有多个 insert 语句,会涉及到频繁的开启事务与提交事务操作,为了提高性能,建议使用手动提交事务


navicat 的数据导入就是手动提交事务的方式

在这里插入图片描述

1.3 按主键的顺序插入

按主键顺序插入数据的性能高于不按主键顺序插入数据,具体的原因可参考本文的 主键优化 章节

1.4 大批量插入数据时使用 load 指令

  • CSV:Comma-Separated Values,逗号分隔值,是一种简单的文件格式,用于存储表格数据,如电子表格或数据库
  • CSV 文件以纯文本形式存储数据,其中每一行代表数据表中的一行,而每行中的数据项通常由逗号分隔
  • CSV 格式因其简单性和通用性而被广泛用于数据交换

如果一次性需要插入大批量数据,使用 insert 语句插入性能较低,此时可以使用 MySQL 数据库提供的 load 指令(数据文件需要是 csv 格式)进行插入


具体操作如下:

连接 MySQL 服务端时,加上 --local-infile 参数

mysql --local-infile -u root -p

设置全局参数 local infile 为 1,打开从本地加载文件导入数据的开关

set global local infile = 1;

执行 load 指令将准备好的数据加载到表结构中

  • FIELDS TERMINATED BY ',':指定字段之间的分隔符
  • LINES TERMINATED BY '\n':指定行结束的标记
load data local infile '/tmp/tb_user.csv' into table 'tb user` fields terminated by ',' lines terminated by '\n';

我们新建一个数据库,用于测试批量插入时使用 insert 语句和使用 load 指令的性能差距

表结构如下

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 80034 (8.0.34)
 Source Host           : localhost:3306
 Source Schema         : blog

 Target Server Type    : MySQL
 Target Server Version : 80034 (8.0.34)
 File Encoding         : 65001

 Date: 29/08/2024 23:13:57
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
  `password` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
  `name` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
  `birthday` date NULL DEFAULT NULL,
  `sex` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `unique_user_username`(`username` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

表中有 100 万条数据,不方便在这里展示,需要的具体数据可以私聊我


使用 insert 语句的耗时(2 分 11 秒)

在这里插入图片描述


delete
from tb_user
where id >= 1;

我们删除表中的数据后,测试使用 load 指令的耗时(30 秒 904毫秒)

在这里插入图片描述

可以看到,使用 load 指令(更准确的来说,是导入 csv 数据格式的文件)导入数据的性能还是不错的

2. 主键优化

在前面我们提到按主键顺序插入数据的性能高于不按主键顺序插入数据,我们现在来剖析一下具体的原因

学习主键优化之前,我们需要先知道在 InnoDB 引擎中,数据的组织方式是怎么样的

2.1 数据组织方式

在 InnoDB 存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(Index Organized Table,简称 IOT)

我们知道,基于 InnoDB 存储引擎的表,索引分为两类——聚集索引和二级索引,聚集索引的叶子结点下面挂的是整一行数据

对于一张表来说,默认主键索引就是聚集索引,所以表中的数据是根据主键的顺序进行存储的,示意图如下

在这里插入图片描述

在 B+Tree 数据结构中,所有的数据都会出现在叶子结点,非叶子节点仅仅起到一个索引数据的作用,而非叶子节点的索引和叶子结点中的数据结构最终都会存放在一个逻辑结构(页,Page)当中,示意图中的黄色部分,就是一个又一个的 Page,每一页的大小是固定的


我们来回顾一下 InnoDB 的逻辑存储结构

在这里插入图片描述

最外层是表空间(Table Space),表空间中存储的是段(Segment),段中存放的是区(Extent),每个区的大小是固定的(1M),区中存放的是页(Page),页中存放的是行(Row),行当中存放的就是具体的字段值

页是 InnoDB 引擎磁盘管理的最小单元,一个页的大小默认为 16 K,我们来看一下,当我们往表中插入数据的时候,大致的流程是怎样的

2.2 页分裂

页可以为空,也可以填充一半,也可以填充 100 %,每个页包含了 2 - N 行数据,根据主键排列(如果一行数据多大,会行溢出)

为什么每一页至少包含两行数据呢,因为如果一个页中只包含一行数据(更一般地说,一条记录),那么当需要在内存中找到多条时,处理器需要连续地访问多个页。这就像是在处理一个链表,每个节点(在这里是页)只包含一个元素(一行数据),要找到下一个元素,你需要跟随链表指针到下一个节点(页)。这种访问方式效率低下,因为它涉及到多次页的换入换出,导致更多的磁盘 IO 操作


我们先来看一下按主键顺序插入数据的情况(相邻的页之间会维护一个双向指针)

在这里插入图片描述


我们再来看一下按主键乱序插入数据的情况

假如现在前两页都存满了数据,这时候需要插入一行 id 为 50 的新数据,但是这个新数据不能存放在新开辟的页中,应该存放在 id 为 47 的数据之后,但第一页已经没有足够的空间来存放 id 为 50 的新数据了

在这里插入图片描述

在这里插入图片描述

那该怎么办呢,MySQL 会开辟一个新的数据页,但 id 为 50 的新数据不会直接存储在新的页中

MySQL 会先找到第一个数据页 50% 的位置,因为 id 为 23 的数据和 id 为 47 的数据在第一个数据页 50% 的位置之后,MySQL 会将 id 为 23 的数据和 id 为 47 的数据移动到新开辟的页中,再将 50 插入到 id 为 47 的数据后面

此时第一页的下一页不应该是第二页,需要改变指针的指向

在这里插入图片描述

以上现象被称为页分裂,主键乱序插入的情况下,就有可能出现页分裂现象,页分裂是比较消耗性能的

介绍了页分裂现象之后,我们再来介绍页合并现象

2.3 页合并

假设数据的存储情况如下

在这里插入图片描述

接下来我们要进行删除操作,在 InnoDB 引擎中,如果我们要删除一行数据,例如 id 为 16 的这一行数据,并不会真正地删除,也就是说并不会在磁盘中直接将 id 为 16 的这一行数据干掉,只是对这一行记录做一个标记,标记这一行数据被删除了

一旦 id 为 16 的数据对应的空间被标记为删除状态,就代表这块空间可以被其它数据占用了

当页中删除的记录达到 MERGE_THRESHOLD(默认为页的 50%),InnoDB 引擎会开始寻找最靠近的页(前或后),看看是否可以将两个页合并,优化空间的使用

在这里插入图片描述

在这里插入图片描述

当有一条 id 为 20 的新数据要插入时,直接插入到第三页中就可以了

以上现象称为页合并

在这里插入图片描述

MERGE THRESHOLD:合并页的阈值,可以自己设置,在创建表或者创建索引时指定

2.4 主键的设计原则

2.4.1 降低主键的长度

在满足业务需求的情况下,尽量降低主键的长度,为什么要降低主键的长度呢,我们需要从聚集索引和二级索引的结构说起,聚集索引是基于主键的,聚集索引只有一个,但二级索引有很多个,二级索引的叶子节点下面挂的数据除了二级索引本身之外,还有主键值

在这里插入图片描述

如果主键的长度比较长,二级索引比较多,将会消耗大量的磁盘空间,在搜索时也会涉及到大量的磁盘 IO,造成性能的下降,所以我们要尽量降低主键的长度

2.4.2 使用 AUTO_INCREMENT 自增主键

插入数据时,尽量选择顺序插入,选择使用 AUTO_INCREMENT 自增主键

2.4.3 尽量不要使用 UUID 或者是其他自然主键(如身份证号)做主键

因为用 UUID 或者是其他自然主键(如身份证号)做主键,主键的值都是不确定的,当有大量数据插入时,可能会频繁地发生页分裂现象,而且 UUID 和其他自然主键(如身份证号)的长度较长,当二级索引很多时,会占用大量的磁盘空间

2.4.4 选择不受业务操作影响的字段作为主键

在选择主键时,选择不受业务操作影响的字段,因为修改主键时底层的数据结构也需要进行调整,代价是比较大的

3. order by 优化

排序有两种方式:

  1. Using fileSort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区 sort_bufer 中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 fileSort 排序
  2. Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高

也就是说,我们在优化 order by 语句的时候,尽量将排序方式优化为 Using index

3.1 测试

接下来我们开始对 order by 语句的测试

我们先查看当前 tb_user 表中有哪些索引

show index from tb_user;

在这里插入图片描述

为了测试结果的准确性,我们把无关的索引删除掉

drop index index_phone_name on tb_user;

drop index index_user_name on tb_user;

drop index index_user_phone on tb_user;

我们运行以下 SQL 语句,查看 SQL 语句的执行计划

explain select id, age, phone
from tb_user
order by age;

在这里插入图片描述

可以看到,Extra 一栏中的值为 Using filesort,排序效率是比较低的


接下来,我们为 age、phone 字段建立一个联合索引

create index index_user_age_phone on tb_user (age, phone);

再次运行 SQL 语句,查看 SQL 语句的执行计划

在这里插入图片描述

可以看到,Extra 一栏中的值为 Using index,排序效率是比较高的


我们运行以下 SQL 语句,查看 SQL 语句的执行计划

explain
select id, age, phone
from tb_user
order by age desc, phone desc;

在这里插入图片描述

可以看到,Extra 一栏中的值为 Using index,但是出现了 Backward index scan; 语句

Backward index scan; 语句表明使用了反向索引扫描,因为创建索引时默认都是按照字段值升序排列的,但是现在我们要倒序返回数据,所以需要反向扫描索引


那如果我们先按照 phone 字段升序排序,再按照 age 字段升序排序呢

explain
select id, age, phone
from tb_user
order by phone, age;

在这里插入图片描述

可以看到,Extra 一栏中有 Using index,也有 Using filesort

因为 SQL 语句违背了最左前缀法则,所以 Extra 字段中会有 Using filesort


那如果我们先按照 age 字段升序,再按照 phone 字段降序呢

在这里插入图片描述

可以看到,Extra 一栏中有 Using index,也有 Using filesort

为什么会出现这种情况呢,因为在创建索引的时候,如果没有指定顺序,默认是按照字段的值升序排列的,也就是先按照 age 值升序,再按照 phone 升序进行排列

我们可以查看索引的结构(Collation 字段中的 A 代表 Asc)

show index from tb_user;

在这里插入图片描述

如果按照 age 字段升序,再按照 phone 字段降序,需要进行额外的排序

那我们要怎么解决这个问题呢,我们可以额外针对 age 字段和 phone 字段创建一个按照 age 字段升序,phone 字段降序的索引

create index index_user_age_phone_asc_desc
    on tb_user (age asc, phone desc);

再次执行 SQL 语句,查看 SQL 语句的执行计划

在这里插入图片描述

可以看到,Extra 一栏中只有 Using index


我们来看一下,刚才创建的 index_user_age_phone 索引和 index_user_age_phone_asc_desc 索引大概是怎么样的

在这里插入图片描述

当然,这些排序规则都建立在你使用了覆盖索引的前提下

在这里插入图片描述

3.2 总结

  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
  • 尽量使用覆盖索引
  • 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC / DESC)
  • 如果不可避免的出现 Using filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认大小为 256 K)
show variables like 'sort_buffer_size';

在这里插入图片描述

如果排序缓冲区满了,MySQL 会在磁盘文件中对数据进行排序,性能比较低

4. group by 优化

在研究 group by 优化时,我们主要研究的是索引对 group by 操作的影响

4.1 测试

在测试前,我们先删除 index_user_profession_age_status 索引

drop index index_user_profession_age_status on tb_user;

drop index index_user_age_phone on tb_user;

drop index index_user_age_phone_asc_desc on tb_user;

执行以下 SQL 语句,查看 SQL 语句的执行计划

explain
select profession, count(*)
from tb_user
group by profession;

在这里插入图片描述

type 字段为 ALL ,说明进行了全表扫描,Using temporary 表明使用了临时表,性能是比较低的


我们针对 profession、age、status 字段创建一个联合索引后再次进行测试

create index index_user_profession_age_status
    on tb_user (profession, age, status);

再次执行 SQL 语句,查看 SQL 语句的执行计划

在这里插入图片描述

可以看到,使用了 index_user_profession_age_status 索引,Extra 字段为 Using index,说明 SQL 语句的执行效率是比较高的


我们根据 profession、age 字段进行分组,查看 SQL 语句的执行计划

explain
select profession, age, count(*)
from tb_user
group by profession, age;

在这里插入图片描述

可以看到,Extra 字段为 Using index,说明 SQL 语句的执行效率是比较高的


我们根据 age 字段进行分组,查看 SQL 语句的执行计划

explain
select age, count(*)
from tb_user
group by age;

在这里插入图片描述

可以看到,Extra 字段出现了 Using filesort,因为不符合最左前缀法则

那不符合最左前缀法则,Extra 字段为什么又会出现 Using index 呢,可能是因为要查询的所有列都包含在索引中(也就是说,索引“覆盖”了查询所需的所有列),那么MySQL可以使用该索引来避免回表操作

在这个例子中,index_user_profession_age_status索引可能包含了 age 列,因此 MySQL 可以使用这个索引来直接获取agecount(*)


我们根据 profession、age 字段进行分组,查看 SQL 语句的执行计划

在这里插入图片描述

可以看到,Extra 字段只有 Using index,因为符合最左前缀法则


我们先根据 profession 字段筛选,再根据 age 字段进行分组,查看 SQL 语句的执行计划

explain
select profession, age, count(*)
from tb_user
where profession = '软件工程'
group by profession, age;

在这里插入图片描述

可以看到,Extra 字段只有 Using index,因为符合最左前缀法则

4.2 总结

  • 在分组操作时,可以通过索引来提高效率
  • 分组操作时,索引的使用也是满足最左前缀法则的

5. limit 优化

如果表的数据比较大,而且页偏移量比较大时,直接使用 limit 语句的效率比较低(这个问题被称作深度分页问题)

例如 limit 2000000,10 ,此时 MySQL 需要排序前 2000010 条记录,但是仅仅返回 [2000000, 2000009] 区间的记录,丢弃其他记录,代价非常大,而且一不小心内存就炸了


那我们怎么对 limit 语句进行优化呢,官方给出的方案是覆盖索引 + 子查询的方式优化

示例如下

explain
select *
from tb_sku,
     (select id from tb_sku order by id limit 2000000,10) as temporary
where tb_sku.id = temporary.id;

6. count 优化

  • MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高
  • InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数

优化思路:自己计数,我们可以借助 key-value 类型的、基于内存的数据库(例如 Redis),每插入一条数据,就让某一个变量自增一次,每删除一条数据,就让某一个变量自减一次,当然这个操作比较繁琐


count 语句的几种使用方式之间的区别

  • count(主键):InnoDB 引擎会遍历整张表,把每一行的主键 id 值都取出来,返回给服务层,服务层拿到主键后,直接按行进行累加主键(因为主键不可能为 NULL)
  • count(字段):
    • 没有 NOT NULL 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为 NULL,不为 NULL 则累加计数
    • 有 NOT NULL 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层直接按行进行累加
  • count(1):InnoDB 引擎遍历整张表,但不取值,服务层对于返回的每一行,放一个数字 1 (不一定要是 1,可以为任意一个常量)进去,直接按行进行累加
  • cout(*):InnoDB 引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加

按效率排序:count(字段) < count(主键) < count(1) < count(*)

所以尽量使用 count(*)

7. update 优化(防止行锁升级为表锁)

我们回想一下,InnoDB 引擎有哪三大特性?(支持事务、支持外键、支持行级锁

7.1 测试

接下来演示行锁升级为表锁的过程

我们先在一个与 MySQL 的连接中开启事务

begin;

然后更新 course 表中 id 为 1 的数据

update course
set name = 'Java'
where id = 1;

执行了更新语句后,InnoDB 会把 id 为 1 的这条数据锁住


我们在另一个与 MySQL 的连接中开启事务

begin;

然后更新 course 表中 id 为 4 的数据

update course
set name = 'C++'
where id = 4;

更新后提交事务

commit;

这时候的更新操作是成功的

更新成功后我们先提交第一个连接中的事务


当前表的数据如下

在这里插入图片描述

我们在第一个连接中再次开启一个事务

begin;

然后将 name 字段为 PHP 的数据改成 Python

update course
set name = 'Python'
where name = 'PHP'

我们在第二个连接中也开启一个事务

begin;

将 id 为 4 的数据的 name 字段改为 RabbitMQ

UPDATE course
SET name = 'RabbitMQ'
WHERE id = 4;

可以发现,更新操作没有执行,而是一直处于阻塞状态

按理说第一个连接锁的不是 id 为 2 对应的数据吗,怎么会影响第二个连接的更新操作?

原因是因为第一个连接在执行 update 语句的时候,name 字段没有建立索引,此时加的是表锁,而不是行锁,所以第二个连接在执行更新操作的时候就阻塞了

第一个连接提交事务后,第二个连接的更新操作就能正常执行了

7.2 总结

执行 update 语句时,InnoDB 的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁

一旦行锁升级为表锁,并发性能就会降低

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

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

相关文章

Javascript归纳与总结——this指向及其改变、new关键字与原型链、异步、闭包和函数防抖与节流

this指向及其改变 普通函数在调用时&#xff0c;this为obj.obj1.fun(),this->obj1,箭头函数在声明定义时this->obj。 Javascript中bind、call、apply區別-CSDN博客 new关键字与原型链 从原型链视角解读VueComponent与Vue关系_vue中重要的原型链关系-CSDN博客 prototy…

开放式耳机是不是智商税?年度开放式耳机推荐2024产品揭秘

现在越来越多的人开始注重耳道健康&#xff0c;开放式耳机也越来越受大家的欢迎&#xff0c;因为这种开放式的设计是不进入耳道&#xff0c;这样能够保护我们的耳道健康&#xff0c;大大减少细菌的滋生。 但是就会有小伙伴说了&#xff0c;那开放式耳机是不是智商税呢&#xff…

iPhone 16 系列和多款新品将亮相,苹果发布会定档 9 月 10 日|TodayAI

苹果公司&#xff08;Apple&#xff09;已正式宣布&#xff0c;将于 2024 年 9 月 9 日举行年度发布会&#xff0c;地点定于苹果园区的史蒂夫乔布斯剧院。此次发布会的主题为 “It’s Glowtime”。发布会预计将带来众多硬件更新和新产品&#xff0c;最受关注的无疑是 iPhone 16…

我的世界实体与生物ID表

猪 Pig JE1.0   Pig 1.7  minecraft:pig 1.11  绵羊 Sheep 羊 JE1.0   Sheep 1.7  minecraft:sheep 1.11  牛 Cow JE1.0   Cow 1.7  minecraft:cow 1.11  鸡 Chicken JE1.0   Chicken 1.7  minecraft:chicken 1.11  鱿鱼 Squid JE1.0   Squid 1.7  m…

字符编码——第一平面的unicode分析

本篇小小探索了下 unicode 第一片面的字符。 一、什么是unicode&#xff1f; Unicode&#xff0c;全称为Unicode标准&#xff08;The Unicode Standard&#xff09;&#xff0c;其官方机构Unicode联盟所用的中文名称为统一码&#xff0c;又译作万国码、统一字符码、统一字符编…

【PyTorch常用库函数】一文向您详解 with torch.no_grad(): 的高效用法

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 在训练神经网络时&#xff0c;我们通常需要计算损失函数关于模型参数的梯度&#xff0c;以便通过梯度下降等优化算法更新参…

ARM内存屏障/编译屏障API(__DMB、__DSB、__ISB)用法及举例

0 参考资料 STM32F7 Series and STM32H7 Series Cortex-M7 processor.pdf ARM Cortex™-M Programming Guide to Memory Barrier Instructions.pdf1 ARM内存屏障/编译屏障指令&#xff08;__DMB、__DSB、__ISB&#xff09;说明 内存屏障和编译屏蔽其实是2个东西&#xff0c;一…

JDBC的使用及案例

1. JDBC基本操作 1.1. JDBC概述 JDBC&#xff08;Java Data Base Connectivity&#xff09;Java连接数据库是一种用于执行SQL语句的Java API&#xff0c;为多种关系数据库提供统一访问它由一组用Java语言编写的类和接口组成有了JDBC&#xff0c;程序员只需用JDBC API写一个程…

将vue项目打包为安卓软件

前言 在我的前一个文章&#xff0c;有讲如何实现一个笔记系统 点击跳转到:纯vue实现笔记系统 那么我如果想要分享给我的朋友该怎么办呢? 那么我将带大家去实现打包安卓软件 安卓实际打包软件 也为了更信服&#xff0c;这里提供一个我的打包之后的软件给大家&#xff0c;感兴…

Python自动化办公2.0 课程更新

之前的课程&#xff0c;包含了Python pandassklearn 数据分析&#xff0c;和Stremlit 可视化仪表盘的开发 和一系列自动化项目案例的开发&#xff0c;包括我们封装了ztl-uia 模块&#xff0c;可以同时自动化操控windows 软件和浏览器, 封装的模块&#xff0c;针对为付费学员使…

证书学习(三).p12证书颁发的5个步骤、如何在线生成证书、证书工具网站推荐

目录 一、证书颁发的 5 个步骤二、在线生成证书2.1 在线生成 CSR 文件2.2 在线 CSR 签发证书三、其他在线工具3.1 在线解析证书3.2 在线证书格式转换(证书转 PKCS#12/DER/JSK 格式)3.3 在线解析 .p12 文件、下载 .cer 文件3.4 直接通过参数设置申请证书【最便捷】四、补充:其…

【职业选择】AI工程师、机器学习工程师和深度学习工程师的职责与工作内容有什么区别?

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

LVGL 控件之进度条(lv_bar)

目录 一、进度条1、概述2、方向3、进度条的当前值和范围值4、进度条模式5、进度条事件6、相关 API 二、例程 一、进度条 1、概述 进度条对象&#xff08;lv_bar&#xff09;有一个背景和一个指示器。指示器的宽度根据进度条的当前值自动设置。 如果设置进度条的宽度小于其高…

[C++] C++11详解 (五)function包装器、bind绑定

标题&#xff1a;[C] C11详解 (五)function包装器、bind 水墨不写bug 目录 一、function包装器 二、bind绑定 正文开始&#xff1a; 一、function包装器 function包装器&#xff0c;function实现在<functional>头文件中。C中的function本质上是一个类模板。 function…

由浅入深学习 C 语言:Hello World【提高篇】

目录 引言 1. Hello World 程序代码 2. C 语言角度分析 Hello World 程序 2.1. 程序功能分析 2.2 指针 2.3 常量指针 2.4 指针常量 3. 反汇编角度分析 Hello World 程序 3.1 栈 3.2 函数用栈传递参数 3.3 函数调用栈 3.4 函数栈帧 3.5 相关寄存器 3.6 相关汇编指令…

离散傅里叶变换(Discrete Fourier Transform, DFT)介绍,地震波分析

介绍 离散傅里叶变换&#xff08;Discrete Fourier Transform, DFT&#xff09;是一种非常重要的信号处理工具&#xff0c;它将离散时间信号从时间域转换到频率域。DFT在信号处理、图像处理、通信系统以及许多其他工程和科学领域中得到了广泛应用。为了理解DFT&#xff0c;我们…

时序预测 | 基于DLinear+PatchTST多变量时间序列预测模型(pytorch)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 DLinearPatchTST多变量时间序列 dlinear,patchtst python代码&#xff0c;pytorch架构 适合功率预测&#xff0c;风电光伏预测&#xff0c;负荷预测&#xff0c;流量预测&#xff0c;浓度预测&#xff0c;机械领域预…

3.美食推荐系统(Java项目springboot和vue)

目录 0.系统的受众说明 1 绪论 1.1研究背景 1.2研究现状 1.3研究内容 2 系统关键技术 2.1 Springboot框架 2.2 JAVA技术 2.3 MYSQL数据库 2.4 B/S结构 3 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2经济可行性 3.1.3操作可行性 3.2 系统性能分析 3.3 系统功能分析 3.4系统…

【3D目标检测】MMdetection3d——nuScenes数据集训练BEVFusion

引言 MMdetection3d&#xff1a;【3D目标检测】环境搭建&#xff08;OpenPCDet、MMdetection3d&#xff09; MMdetection3d源码地址&#xff1a;https://github.com/open-mmlab/mmdetection3d/tree/main?tabreadme-ov-file IS-Fusion源码地址&#xff1a;https://github.co…