MySQL: 索引与事务

文章目录

  • 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)
begindeclare return_str varchar(255) default '';declare i int default 0;while i < n do if i=0 thenset return_str = rand_string(l);elseset 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)
begindeclare 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 thenset return_str 
=concat(return_str,substring(upper_str,floor(1+rand()*26),1));elseset 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)
begindeclare 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;  repeatset i = i + 1;insert into test_user values ((start+i) ,rand_name(2, 
5),rand_num(120),CURRENT_TIMESTAMP);until i = max_numend 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: 1select_type: SIMPLEtable: test_usertype: ALL
possible_keys: NULLkey: NULL <== keynull表示没有用到索引key_len: NULLref: NULLrows: 6Extra: 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: 1select_type: SIMPLEtable: test_usertype: ref
possible_keys: idx_test_user_id_numberkey: idx_test_user_id_number <= key用到了idx_test_user_id_numberkey_len: NULLref: constrows: 1Extra: 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.mzph.cn/web/25594.shtml

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

相关文章

深入STL之 栈与队列:数据结构探索之旅

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模拟实现list与迭代器 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀stack和queue &#x1f4…

探索软件工程师在新能源汽车研发中的角色与贡献

随着全球对可持续发展的关注不断增加&#xff0c;新能源汽车的研发与应用成为了汽车行业的一个重要方向。作为软件工程师&#xff0c;参与新能源汽车研发不仅能够推动科技创新&#xff0c;还能为环保事业贡献力量。本文将深入探讨软件工程师在新能源汽车研发中的具体贡献、所需…

C#操作MySQL从入门到精通(20)——更新数据

前言: 谈到数据库,大家最容易脱口而出的就是增删改查,本文所说的更新数据就是增删改查的改,改变数据的意思。 本文测试使用的数据库如下: 1、更新一列 所谓更新一列的意思就是只更改一列数据,并且通常要使用where条件,因为不加这个条件的话会导致将所有行的数据进行…

数据可视化Python实现超详解【数据分析】

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Python 初阶 Python–语言基础与由来介绍 Python–…

后端服务器启动访问

VisualStudioCode(VSCode) 服务器启动 浏览器中测试访问 http://localhost:3000

算法笔记1-高精度模板(加减乘除)个人模板

目录 加法 减法 乘法 ​编辑 除法 加法 #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue>using namespace std;typedef pair<int,int> PII;const int N 1e5 10;int n; int a[N],…

ROS学习记录:C++节点发布自定义地图

前言 ROS栅格地图格式 在了解了ROS地图消息包的数据结构后(链接在上)&#xff0c;本文将编写一个节点&#xff0c;发布地图消息包&#xff0c;看看在RViz中显示是什么效果。 一、准备 1、为了简单起见&#xff0c;发布一个两行四列的地图 2、为了便于观测&#xff0c;只对地…

SmartEDA VS Multisim/Proteus:电子设计江湖,谁主沉浮?

在电子设计的江湖里&#xff0c;SmartEDA、Multisim和Proteus无疑是几大门派&#xff0c;各自拥有独特的武功秘籍和门派特色。今天&#xff0c;我们就来一场巅峰对决&#xff0c;看看这些电子设计软件究竟谁能笑傲江湖&#xff0c;成为电子设计界的霸主&#xff01; 一、门派起…

Seq2seq、编码器解码器神经网络

目录 一、Seq2seq 简介二、编码器三、解码器四、编码器-解码器的训练 遇到看不明白的地方&#xff0c;欢迎在评论中留言呐&#xff0c;一起讨论&#xff0c;一起进步&#xff01; 需掌握的前提知识&#xff1a; LSTM、词嵌入 本文参考&#xff1a;【官方双语】编码、解码神经网…

tkinter菜单栏

tkinter菜单栏 菜单栏效果代码 菜单栏 在 Tkinter 中&#xff0c;Menu 组件用于创建菜单栏、下拉菜单和上下文菜单&#xff0c;是构建图形用户界面&#xff08;GUI&#xff09;应用程序的常见需求。 效果 代码 import tkinter as tk from tkinter import messagebox# 创建主…

DAMA学习笔记(一)-数据管理

1.引言 数据管理(Data Management) 是为了 交付、 控制、 保护 并 提升 数据和信息资产的 价值 , 在其整个生命周期中制订 计划、 制度、 规程和实践 活动, 并 执行 和 监督 的过程。 数据管理专业人员(Data Management Professional) 是指 从事数据管理各方面的工作…

MySQL与PostgreSQL关键对比三(索引类型)

目录 索引类型 B-tree 索引 Hash 索引 Full-text 索引 GiST 索引 GIN 索引 BRIN 索引 索引创建示例 MySQL PostgreSQL 结论 以下SQL语句的执行如果需要开发工具支持&#xff0c;可以尝试使用SQLynx或Navicat来执行。 MySQL和PostgreSQL在索引方面有许多相似之处&am…

【C#线程设计】2:backgroundWorker

实现&#xff1a; &#xff08;1&#xff09;.控件&#xff1a;group Box&#xff0c;text Box&#xff0c;check Box&#xff0c;label&#xff0c;botton&#xff0c;richtextbox 控件拉取见&#xff1a;https://blog.csdn.net/m0_74749240/article/details/139409510?spm1…

吴恩达2022机器学习专项课程C2W3:2.25 理解方差和偏差(诊断方差偏差正则化偏差方案)

目录 引言名词替代影响模型偏差和方差的因素1.多项式阶数2.正则化参数 判断是否有高偏差或高方差1.方法一&#xff1a;建立性能基准水平2.方法二&#xff1a;建立学习曲线 总结 引言 机器学习系统开发的典型流程是从一个想法开始&#xff0c;然后训练模型。初次训练的结果通常…

C语言最终讲:预处理详解

C语言最终讲&#xff1a;预处理详解 1.预定义符号2.#define定义常量3.#define定义宏4.带有副作用的宏参数5.宏替换的规则6.宏和函数的对比6.1宏的优势6.1.1\符号 6.2宏的劣势 7.#和##7.1#运算符7.2##运算符 8.命名约定9.#undef10.命令行定义11.条件编译12.头文件的包含12.1本地…

13. UDP协议与RTP协议

UDP协议 UDP协议比较简单&#xff1a; UDP的长度是固定的&#xff0c;用总长度-UDP长度就是数据长度。 UDP是不保证他的有序性和可靠性的。对于音频和视频是这样是比较好的&#xff0c;因为这段丢了&#xff0c;我们可以从下一段在开始解码。 RTP RTP 协议概述 RTP&#x…

【MySQL】(基础篇六) —— 过滤数据

过滤数据 本文将讲授如何使用SELECT语句的WHERE子句指定搜索条件。 WHERE子句 数据库表一般包含大量的数据&#xff0c;很少需要检索表中所有行。通常只会根据特定操作或需要提取表数据的子集。只检索所需数据需要指定搜索条件&#xff08;search criteria&#xff09;&…

代码随想录算法训练营第36期DAY56

DAY56 套磁很顺利&#xff0c;发现又有书读了&#xff01; 300最长递增子序列 朴素法&#xff0c;这个好想&#xff0c;但是不对&#xff0c;比如 0 1 0 3 2 3 我的算法会找出0 1 3作为答案&#xff0c;而不是0 1 2 3 可以看出&#xff0c;后面的状态依赖于前面的状态&am…

Facebook革新:数字社交的下一个阶段

在数字化时代&#xff0c;社交网络已经成为人们生活中不可或缺的一部分。作为全球最大的社交网络平台之一&#xff0c;Facebook一直在不断创新&#xff0c;引领着数字社交的发展。然而&#xff0c;随着科技的不断进步和社交需求的变化&#xff0c;Facebook正在走向一个新的阶段…

Gitte的使用(Windows/Linux)

Gitte的使用&#xff08;Windows/Linux&#xff09; 一、Windows上使用Gitte1.下载程序2.在Gitte上创建远程仓库3.连接远程仓库4.推送文件到远程仓库 二、Linux上使用Gitte1.第一次从仓库上传1.1生成公钥1.2配置SSH公钥1.3新建一个仓库1.4配置用户名和邮箱在Linux中1.5创建仓库…