MySQL: 索引与事务

news2024/9/20 18:34:36

文章目录

  • 1. 索引 (Index)
    • 1.1 概念
    • 1.2 作用
    • 1.3 使用场景
    • 1.4 索引的使用
    • 1.5 索引的使用案例 (不要轻易尝试)
    • 1.6 索引背后的数据结构
    • 1.7 重点总结
  • 2.事务
    • 2.1 为什么要使用事务
    • 2.2 事务的概念
    • 2.3 事务的使用
    • 2.4 对事务的理解
    • 2.5 事务的基本特性

1. 索引 (Index)

1.1 概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。

对索引的理解

  1. 数据库中的索引可以理解为书目录 (跟C/Java中的下标有所区别) , 为了加快查询的速度.
  2. 数据库中select的查询操作, 默认是按照 “遍历” 的方式来完成查询操作的, 消耗时间很大.
  3. "索引"就相当于在数据库中构建一个特殊的 “目录” , 通过这种数据结构, 加快查询速度, 尽可能避免针对数据进行遍历操作, 大大加快了查询速度.
  4. “索引” 虽然会加快查询速度, 但是需要付出一定的代价
    1)引入索引会消耗额外的存储空间
    2)引入索引后确实会提高查询的效率, 但是可能会影响到增删改的效率(可能变快, 也可能变慢, 也可能不变).
  5. 索引有利有弊, 在实际开发中, 推荐使用索引
    1)硬盘往往不是主要消耗矛盾
    2)对于增删改不一定都是负面影响, 也有很多正面效果, 另一方面, 很多业务场景当中, 查询的场景比增删改要高得多…

1.2 作用

  • 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。
  • 索引所起的作用类似书籍目录,可用于快速定位、检索数据。
  • 索引对于提高数据库的性能有很大的帮助。
    在这里插入图片描述

1.3 使用场景

要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外的磁盘空间。

满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

1.4 索引的使用

创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。

-- 查看索引
show index from 表名;

-- 案例: 查看学生表已有的索引
show index from student;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table   | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student |          0 | PRIMARY    |            1 | id          | A         |           8 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| student |          1 | classes_id |            1 | classes_id  | A         |           2 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
-- Key_name 这一列是索引名字, 如primary是给主键列自动生成的索引 
-- 主键索引(不需要手动创建, 只需要建表的时候, 制定了主键就会自动生成主键索引)
-- column_name 这一列是索引创建的依据列名
-- 创建索引
-- 对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(字段名);

-- 案例:创建班级表中,name字段的索引
create table classes(
id int primary key auto_increment,
name varchar(20), 
`desc` varchar(100));

desc classes;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int          | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)  | YES  |     | NULL    |                |
| desc  | varchar(100) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

create index idx_classes_name on classes(name);

desc classes;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int          | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)  | YES  | MUL | NULL    |                |
| desc  | varchar(100) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
-- 可以看到Key这一列的变化

注意:
创建索引是一个危险操作, 如果针对空表或者表里面的数据量很少(几千, 几万…) 创建索引并无大碍, 一旦表的数据量比较大, 千万级别的数据量, 此时创建索引就可能会触发大量的硬盘IO, 直接把机器搞得卡死了…
所以, 在最初创建表的时候, 有需要哪些索引就需要提前规划好, 创建好…
解决方法: 万一某个表需要索引, 但是没有提前创建, 可以再申请一个服务器, 把表创建好, 再导入数据.

-- 删除索引(只能删除自建索引)
drop index 索引名 on 表名;

-- 案例:删除班级表中name字段的索引
drop index idx_classes_name on classes;

1.5 索引的使用案例 (不要轻易尝试)

准备测试表:

-- 创建用户表
DROP TABLE IF EXISTS test_user;
CREATE TABLE test_user (
 id_number INT,
 name VARCHAR(20) comment '姓名',
 age INT comment '年龄',
 create_time timestamp comment '创建日期'
);

准备测试数据,批量插入用户数据(操作耗时较长,约在1小时+):

-- 构建一个8000000条记录的数据
-- 构建的海量表数据需要有差异性,所以使用存储过程来创建, 拷贝下面代码就可以了,暂时不用理解

-- 产生名字
drop function if exists rand_name;
delimiter $$
create function rand_name(n INT, l INT)
returns varchar(255)
begin
 declare return_str varchar(255) default '';
 declare i int default 0;
 while i < n do 
 if i=0 then
 set return_str = rand_string(l);
 else
 set return_str =concat(return_str,concat(' ', rand_string(l)));
 end if;
 set i = i + 1;
 end while;
 return return_str;
 end $$
delimiter ;

-- 产生随机字符串
drop function if exists rand_string;
delimiter $$
create function rand_string(n INT)
returns varchar(255)
begin
 declare lower_str varchar(100) default
 'abcdefghijklmnopqrstuvwxyz';
 declare upper_str varchar(100) default
 'ABCDEFJHIJKLMNOPQRSTUVWXYZ';
 declare return_str varchar(255) default '';
 declare i int default 0;
 declare tmp int default 5+rand_num(n);
 while i < tmp do 
 if i=0 then
 set return_str 
=concat(return_str,substring(upper_str,floor(1+rand()*26),1));
 else
 set return_str 
=concat(return_str,substring(lower_str,floor(1+rand()*26),1));
 end if;
 
 set i = i + 1;
 end while;
 return return_str;
 end $$
delimiter ;

-- 产生随机数字
drop function if exists rand_num;
delimiter $$
create function rand_num(n int)
returns int(5)
begin
 declare i int default 0;
set i = floor(rand()*n);
return i;
end $$
delimiter ;

-- 向用户表批量添加数据
drop procedure if exists insert_user;
delimiter $$
create procedure insert_user(in start int(10),in max_num int(10))
begin
declare i int default 0; 
set autocommit = 0;  
 repeat
 set i = i + 1;
 insert into test_user values ((start+i) ,rand_name(2, 
5),rand_num(120),CURRENT_TIMESTAMP);
 until i = max_num
 end repeat;
 commit;
end $$
delimiter ;

-- 执行存储过程,添加8000000条用户记录
call insert_user(1, 8000000);

查询 id_number 为778899的用户信息:

-- 可以看到耗时4.93秒,这还是在本机一个人来操作
-- 在实际项目中,如果放在公网中,假如同时有1000
个人并发查询,那很可能就死机。
select * from test_user where id_number=556677;

在这里插入图片描述
可以使用explain来进行查看SQL的执行:

explain select * from test_user where id_number=556677;
*************************** 1. row ***************************
           id: 1
 select_type: SIMPLE
        table: test_user
         type: ALL
possible_keys: NULL
         key: NULL <== keynull表示没有用到索引
     key_len: NULL
         ref: NULL
         rows: 6
       Extra: Using where
1 row in set (0.00 sec)

为提供查询速度,创建 id_number 字段的索引:

create index idx_test_user_id_number on test_user(id_number);

换一个身份证号查询,并比较执行时间:

select * from test_user where id_number=776655;

在这里插入图片描述
可以使用explain来进行查看SQL的执行:

explain select * from test_user where id_number=776655;
*************************** 1. row ***************************
           id: 1
 select_type: SIMPLE
        table: test_user
         type: ref
possible_keys: idx_test_user_id_number
         key: idx_test_user_id_number <= key用到了idx_test_user_id_number
     key_len: NULL
         ref: const
         rows: 1
       Extra: Using where
1 row in set (0.00 sec)

索引保存的数据结构主要为B+树,及hash的方式, 对这方面感兴趣可给个关注, 后面会持续更新.

1.6 索引背后的数据结构

"构建索引"就是引入一些数据结构, 对数据进行存储, 从而提高查找的速度.
我们在学习数据结构的时候可以知道, 二叉搜索树和哈希表都可以提高数据的查找速度, 但是并不适合给数据库做索引, 原因如下:

  1. 二叉搜索树, 最大的问题在于"二叉" 当保存数据的元素较多的时候, 就会使整个树的高度变得比较高, 查询时, 比较次数就会变多, 会伤硬盘.
  2. 哈希表, 最大问题在于只能进行"相等" 查询, 无法进行 > < 这样的"范围查询", 也无法进行like的模糊查询

B树(B- 树), 是N叉搜索树, 每个节点就能有多个子树了(树的度是N), 这样就会降低树的高度, 每个节点上会存多个key值, 保存了N个key值就可以延伸出N + 1个子树了. 此时, 当我们查询时, 针对每个节点, 都需要比较多次, 才能确定下一步走哪个区间了. 此时虽然高度降低了, 但是比较次数变多了, 但是还是会比二叉树有优势, 每次访问节点时, 一次硬盘IO就可以了, 剩下的比较在内存中进行. B树主要目的不是减少比较次数, 而是降低内存IO次数来提升效率.

B+树, 为数据库量身定制的数据结构~~针对B树又一步改进了,
1)B+树也是一个N叉搜索树, 不同于B树, B+树有N个key划分出N个区间.
2)父节点的key值会在下一个子节点再次出现, 是以子节点最大值出现的, 看是浪费空间, 实际上非常有用.
3)B+ 树把子叶结点像链表一样首尾相连了, 类似双向链表的结构, 进行范围查询时就会非常方便了. 每次查询, 经历的IO次数和比较次数都是差不多的, 查询的开销比较稳定. (稳定的优势很大, 意味着开发成本容易被预估出来…)
4)由于B+ 树叶子结点是全集, 非叶子节点上不必存储"数据行", 只需要存储索引列的key即可, 使得非叶子节点消耗的空间比较少. 甚至可以直接加载到内存中进行, 有进一步减少了硬盘IO.

1.7 重点总结

经典面试题: 谈谈对索引的理解
1.索引是什么?解决了什么问题?
索引相当于书的目录, 能够提高查询的速度…

2.索引付出了什么代价?
1)需要更多的存储空间
2)可能会影响增删改的速率(不一定全都是负面影响)
整体来说, 索引利大于弊, 日常开发还是要常用

3.如何使用sql操作索引, 是否有注意事项.

1)show index from 表名; -- 查看索引 (主键, 外键, unique 会自动生成索引, 不可删除)
2)create index 索引名 on 表名(列名); -- 给指定列创建索引, 可以删除
3)drop index 索引名 on 表名; -- 删除索引

注意事项
索引是针对列来创建的, 后续查询的时候, 查询条件使用的列和索引列匹配, 才能使索引生效, 才能提高查询速率
针对一个比较大的表 (有上千万条数据) , 创建或者删除索引是非常危险的, 可能会触发大量的硬盘IO, 把机器高挂了

4.索引背后的数据结构 => B+ 树特点和优势
特点:
1)N叉搜索树, 每个节点上包含N个key, 划分出N个区间
2)每个父节点中的元素, 都会下沉到子节点中, 作为孩子节点中最大的角色来存在
3)叶子结点这一层就构成了数据集合的全集
4)使用类似于链表这样的结构, 把叶子结点串起来
优势:
1)N叉搜索树, 高度比较低, 降低了硬盘IO的次数
2)范围查询非常高效且方便
3)所有的查询都落在叶子结点上, 开销非常稳定, 容易预估成本
4)叶子结点存储数据行, 非叶子节点只存储索引列的key 值, 非叶子节点占据空间小, 可以加载到内存中进一步减少查询时IO的访问次数

2.事务

2.1 为什么要使用事务

准备测试表

create table accout(
 id int primary key auto_increment,
 name varchar(20) comment '账户名称',
 money decimal(11,2) comment '金额'
);
insert into accout(name, money) values
('阿里巴巴', 5000),
('四十大盗', 1000);

比如说,四十大盗把从阿里巴巴的账户上偷盗了2000元

-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';

假如在执行以上第一句SQL时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少2000,但是四十大盗的账户上就没有了增加的金额。

解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败。

2.2 事务的概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

2.3 事务的使用

(1) 开启事务: start transaction;
(2) 执行多条SQL语句
(3) 回滚或提交: rollback/commit;
说明:rollback即是全部失败,commit即是全部成功。

start transaction;
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;

2.4 对事务的理解

开启事务后, 并不是一起执行语句, 还是一条一条执行的, 当执行到事物的墨条语句发生错误就会自动进行"还原操作", 相当于把前面执行过的sql给撤销, 最终的效果好像是一个都没执行的效果. 这样的机制也称为"回滚" (rollback).
同时, 也把事务支持的上述的"特性" 称为 “原子性”

数据库如何知道怎样回滚的?(前面的SQL语句对表做出了怎样的修改?)
数据库内部存在一系列的 “日志体系”, 记录到文件中
当开启事务后, 此时每一步执行的SQL语句对数据的修改情况就会记录到文件里面, 后续如果需要回滚, 就可以参考之前记录的内容进行还原了.
这样, 我们就可以应对防止回滚操作时"程序崩溃" 或者 “主机掉电” 的情况造成数据丢失.

事务的核心就是原子性, 能够解决批量执行SQL语句 (转账, 点外卖, 记录学生信息…) 时造成的错误

2.5 事务的基本特性

1.原子性 (最重要)
2.一致性 描述的是事务执行前和执行后, 数据库中的数据都是 “合法状态” , 不会出现非法的临时结果状态. (类似于 “对账” 的过程)
3.持久性 事务执行完毕之后, 就会修改硬盘上的数据, 事务是持久生效的.
4.隔离性(最难)
隔离性, 描述了多个实物并发执行的时候, 相互之间产生影响是怎样的.
并发执行, MySQL是一个 “客户端-服务器” 结构的程序, 一个服务器, 通常会给多个客户端同时提供服务, 因此, 多个客户端就同时给这个服务器提交事务来执行, 与之相对, 服务器就需要同时执行这多个事务, 此时就是 “并发” 执行的.
如果这些同事执行的事务对同一张表进行增删改查, 就会引入一些问题, 问题如下

1)脏读
有两个事务A和B并发执行, A在对数据修改的过程中, B去读取这个表的数据, B读取完成后, A又把数据给改了, 就导致B读取的数据不是一个正确的想要的数据, 而是读到了A执行过程中的一个临时数据, 这个临时数据就称作"脏数据". (数据过期了, 过时了)
如何去解决这个问题呢?
我们可以在执行事务A时进行加锁, 让事务B在事务A执行时不能读表中的数据, 具体如何加锁会在后面的博客更新, 希望大家持续关注…
2)不可重复读
有三个事务, 事务A, B, C.当事务A执行修改操作完成后, 提交数据. 事务B开始执行, 读取事务A修改后的数据, 在执行过程中, 事务C执行, 修改事务A修改后的数据, 完成后并提交数据(此时事务B并未结束), 这时, 事务B在执行时读到的数据就会和之前的不一样, 这个过程叫做"不可重复读". (事务B多次读取到的结果不一样, 如果是多个事务读到的结果不一样属于正常情况)
如何解决这个问题?
给读操作加锁, 当一个事物读取数据时, 其他事务不能对这个数据进行修改
3)幻读
相当于不可重复读的特殊情况
有一个事务A在读取数据的时候, 事务B对当前数据进行增加或者删除, 这就造成事务A在多次读取的时候, 得到的结果不一样, 就称作幻读. (相对于不可重复读没那么严重)
如何解决这个问题?
规定当一个事物读取数据时, 其他事务不进行任何操作, 这样的操作就成为"串行化" (如: 当多个客户端同时提交多个事务过来, 我们一个一个执行事务)

MySQL中提供了四个隔离级别, 通过配置文件可以来设置当前服务器的隔离级别, 根据实际需要来选择
设置不同的隔离级别, 就会使事物之间的并发执行的影响产生不同的差别, 从而影响到上述的三个情况
并发程度越高, 执行速度越快; 并发程度越低, 执行速度越慢
1)read uncommitted (读未提交)
这种情况下, 一个事物可能读取另一个事务未提交的数据, 此时就可能产生脏读, 不可重复读, 幻读 三种问题, 但是此时, 多个事务并发执行程度是最高的, 执行速度也是最快的.
2)read committed (读已提交)
这个情况下, 一个事务只能读另一个事务提交之后的数据 (给写操作加锁了), 此时, 可能会产生不可重复读, 幻读问题 (脏读问题解决了), 此时并发程度会降低, 执行速度相对减慢. 事物之间的隔离性相对提高了.
3)repeatable read (可重复读)
这个情况下, 相当于给写操作和读操作都加锁了, 此时可能产生幻读问题, 解决了脏读和不可重复读问题, 并发程度进一步降低, 执行速度进一步变慢, 事物之间的隔离性进一步提高了
4)serializable (串行化)
此时所有事务都是在服务器上一个一个执行的, 事务之间的隔离性进一步提高了, 解决了脏读, 不可重复读, 幻读问题, 并发程度最低, 执行速度最慢, 隔离性最高.
MySQL默认隔离级别为第三个…

啥时候需要准?
算钱…
啥时候需要快, 对于准不要求?
短视频的点赞数, 转发数, 评论数… 这些数据要快, 但是不要求准, 用户才能使用流畅…

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

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

相关文章

深入探索 Rust 的 clap 库:命令行解析的艺术

版本声明 Rust: 1.76clap: 4.5.1clap_complete 4.5.1rpassword: 7.3.1 结论先行 本文将从 CLI&#xff08;Command Line Interface&#xff09;命令行工具的概述讲起&#xff0c;介绍一个优秀的命令行工具应该具备的功能和特性。然后介绍 Rust 中一个非常优秀的命令行解析工…

双Token方案实现Token自动续期(基于springboot+vue前后端分离项目)

文章目录 前言一、双Token方案介绍1. 令牌类型与功能2.双Token方案的优点3.实现流程 二、具体实现1.后端实现1.1 jwt工具类1.2 响应工具类1.3 实体类1.4 过滤器1.5 controller1.6 启动类 2、前端实现2.1 登录页面2.2 index页面2.3 请求拦截器和响应拦截器 效果展示 前言 更多j…

Windows11下Docker使用记录(五)

目录 准备1. WSL安装cuda container toolkit2. win11 Docker Desktop 设置3. WSL创建docker container并连接cuda4. container安装miniconda&#xff08;可选&#xff09; Docker容器可以从底层虚拟化&#xff0c;使我们能够在 不降级 CUDA驱动程序的情况下使用 任何版本的CU…

【李宏毅-生成式 AI】Spring 2024, HW5:LLM Fine-tuning 实验记录

文章目录 1. Task Overview2. Overall Workflow3. Dataset 介绍4. 代码介绍4.1 环境介绍4.2 下载 dataset4.3 下载并加载模型4.2 Notebook 代码1&#xff09;import 部分2&#xff09;固定 seed3&#xff09;加载 LLM4&#xff09;加载 tokenizer5&#xff09;设置解码参数6&am…

C++期末复习提纲(血小板)

目录 1.this指针 2.静态成员变量 3.面向对象程序设计第一阶段 4.面向对象程序设计第二阶段 5.面向对象程序设计第三阶段 6.简答题 &#xff08;1&#xff09;拷贝构造函数执行的三种情况&#xff1a; &#xff08;2&#xff09;虚析构函数的作用&#xff1a; &#xff…

Java面试_数据库篇_优化,事务,Mysql

Java面试_数据库篇_优化,事务,Mysql 优化如何定位慢查询方案一: 开源工具方案二: Mysql自带慢日志 如何分析慢SQL语句索引介绍索引聚簇索引和非聚簇索引&#xff0c;回表查询覆盖索引&#xff0c;超大分页优化索引创建的原则索引失效 谈谈sql优化的经验 事务事务特性隔离级别un…

算法:位运算题目练习

目录 常见的位运算的操作总结 ①基础位操作 ②给一个数n&#xff0c;确定它的二进制表示中的第x位是0还是1 ③将一个数n的二进制表示的第x位修改成1 ④将一个数n的二进制表示的第x位修改成0 ⑤位图的思想 ⑥提取一个数n二进制表示中最右侧的1 ⑦干掉一个数n二进制表示中…

无人机、机器人10公里WiFi远距离图传模块,实时高清视频传输,飞睿CV5200模组方案,支持mesh自组网模块

在快速发展的物联网时代&#xff0c;远距离无线通信技术已成为连接各种智能设备的关键。无人机、安防监控、机器人等领域对数据传输的距离和速度要求越来越高。 公里级远距离WiFi模组方案可以通过多种技术和策略的结合来实现无人机和机器人之间的高效通信传输。 飞睿智能CV52…

QT C++ QTableWidget 表格合并 setSpan 简单例子

这里说的合并指的是单元格&#xff0c;不是表头。span的意思是跨度、宽度、范围。 setSpan函数需要设定行、列、行跨几格&#xff0c;列跨几格。 //函数原型如下 void QTableView::setSpan(int row, i nt column, 、 int rowSpanCount,/*行跨过的格数*/ int columnSpanCount…

离散数学答疑 5

知识点&#xff1a;单侧连通&#xff0c;强连通&#xff0c;弱连通 前缀码&#xff1a;比如001和00101就不是。因为后者的前三位和前者的重复了 有向图的邻接矩阵求法&#xff1a;横着看 数据结构21-4分钟搞定邻接矩阵_哔哩哔哩_bilibili 可达矩阵是包含自反性的。可达矩阵是…

Excel 将同一分类下的值依次填进分类格右边的格中

表格的第2列是分类&#xff0c;第3列是明细&#xff1a; ABC1S.noAccountProduct21AAAQatAAG32BAAQbIAAW43BAAQkJAAW54CAAQaAAP65DAAQaAAX76DAAQbAAX87DAAQcAAX 需要将同一分类下的值依次填入分类格右边的格中&#xff1a; ABCD1S.noAccountProduct21AAAQatAAG32BAAQbIAAWkJ…

13 RTP包的使用

RTP RTP包最主要的就是Sequence number。 对于发送者来说&#xff0c;视频的每一个帧都有很多包组成。对于接收端来接收的时候是有一个队列进行接收的。这个队列大小都是通过计算的。有了队列之后就会不断的往队列中插入数据。当队列中有的数据超时一直组不成包的时候&#xf…

国资e学快速学习实战教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

[FreeRTOS 基础知识] 任务调度 与 链表

文章目录 任务并行的概念RTOS如何实现多任务调度&#xff1f; 任务并行的概念 在生活中&#xff0c;经常出现一心多用的情况。比如你需要一边吃饭一边手机回复信息&#xff0c;这里面就存在两个任务&#xff1a;任务一、吃饭。任务二、手机回复信息。 假如你无法一心多用&…

IO进程线程(十二)进程间通信 共享内存 信号灯集

文章目录 一、共享内存 shared memory&#xff08;shm&#xff09;&#xff08;一&#xff09;特点&#xff08;二&#xff09; 相关API1. 创建共享内存2. 映射共享内存到当前的进程空间3. 取消地址映射4. 共享内存控制 &#xff08;三&#xff09;使用示例&#xff08;四&…

08-指针与数组的结合——数组指针与指针数组的区别

指针与数组的结合 示例 1:指针访问数组元素 通过指针访问数组元素的例子&#xff1a; #include <stdio.h>int main() {int arr[5] {1,2,3,4,5};//int *p1 &arr;int *p1 (int *)&arr; // 需要强制类型转换int *p2 arr;printf("*p1:%d\n", *(p1 …

【SQL】牛客网SQL非技术入门40道代码|练习记录

跟着刷题&#xff1a;是橘长不是局长哦_哔哩哔哩_bilibili 6查询学校是北大的学生信息 select device_id, university from user_profile where university 北京大学 7查找年龄大于24岁的用户信息 select device_id, gender, age, university from user_profile where age…

大模型训练的艺术:从预训练到增强学习的四阶段之旅

文章目录 大模型训练的艺术&#xff1a;从预训练到增强学习的四阶段之旅1. 预训练阶段&#xff08;Pretraining&#xff09;2. 监督微调阶段&#xff08;Supervised Finetuning, SFT&#xff09;3. 奖励模型训练阶段&#xff08;Reward Modeling&#xff09;4. 增强学习微调阶段…

关于 Redis 中集群

哨兵机制中总结到&#xff0c;它并不能解决存储容量不够的问题&#xff0c;但是集群能。 广义的集群&#xff1a;只要有多个机器&#xff0c;构成了分布式系统&#xff0c;都可以称之为一个“集群”&#xff0c;例如主从结构中的哨兵模式。 狭义的集群&#xff1a;redis 提供的…

C++~~期末复习题目讲解---lijiajia版本

目录 1.类和对象 &#xff08;3&#xff09;创建对象的个数 &#xff08;3&#xff09;全局变量&#xff0c;局部变量 &#xff08;4&#xff09;构造函数的执行次数 &#xff08;5&#xff09;静态动态析构和构造顺序 &#xff08;6&#xff09;初始化顺序和声明顺序 &a…