【MySQL】

这里写目录标题

  • MySQL架构
  • 一条sql执行流程
  • MySQL数据存放电脑位置
  • ibd文件结构
  • 行溢出是什么
  • MySQL行记录存储格式
  • 索引
  • 为什么InnoDB选择B+树作为索引数据结构
  • 什么时候需要创建索引
  • 优化索引方法
  • InnoDB内部怎么存储数据
  • B+ 树如何进行查询
  • 聚簇索引和二级索引
  • 为什么MySQL要采用B+树作为索引底层结构呢?
    • 1.0 线性查找
    • 2.0 二叉查找树
    • 3.0 平衡二叉树
    • 4.0 B 树
    • B+ 树
    • InnoDB里的B+树

MySQL架构

MySQL 的架构共分为两层:Server 层存储引擎层

Server层
Server 层主要负责建立连接、分析和执行 SQL。MySQL 里大多数的核心功能模块都在这实现,主要包括连接器,查询缓存、解析器、预处理器、优化器、执行器等。另外,所有的内置函数和所有跨存储引擎的功能比如存储过程、触发器等都在 Server 层实现。

存储引擎层
存储引擎层主要负责数据的存储和提取。MySQL支持多个存储引擎,不同的存储引擎共用一个 Server 层。从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+树 ,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。

一条sql执行流程

在这里插入图片描述

第一步:通过连接器进行连接
我们首先需要连接 MySQL 服务器,然后才能执行 SQL。因为 MySQL 是基于 TCP 协议进行传输的,所以连接的过程需要先经过 TCP 的三次握手。
第二步:查询缓存
如果 SQL 是查询语句,MySQL 就会先去缓存里查找缓存数据,看看之前有没有执行过这一条命令,这个查询缓存是以 key-value 形式保存在内存中的,key 为 SQL 查询语句,value 为 SQL 语句查询的结果。
如果查询的语句命中查询缓存,那么就会直接返回 value 给客户端。如果查询的语句没有命中查询缓存中,那么就要往下继续执行,等执行完后,查询的结果就会被存入查询缓存中。

但其实对于更新比较频繁的表,查询缓存的命中率很低的,因为只要一个表有更新操作,那么这个表的查询缓存就会被清空。如果刚缓存了一个查询结果很大的数据,还没被使用的时候,刚好这个表有更新操作,查询缓冲就被清空了,那这样也太浪费资源了。所以,MySQL 8.0 版本直接将查询缓存删掉了。

第三步:解析器解析 SQL
在正式执行 SQL 查询语句之前, MySQL 会先对 SQL 语句做解析,这个工作交由「解析器」来完成。
解析器会做如下两件事情。

1,词法分析。MySQL 会根据你输入的字符串识别出关键字,比如表名、字段名、where条件这些,并且构建出 SQL 语法树。
2,语法分析。也就是检验我们输入的 SQL 语句语法是否正确,比如把 from 写成了 form,这时 MySQL 解析器就会报错。

第四步:执行SQL
SELECT 查询语句流程主要可以分为三个阶段:

1、预处理阶段
检查 SQL 查询语句中的表或者字段是否存在;把 select* 中的 * 符号,扩展为表上的所有列;
2、优化阶段
优化器主要负责将 SQL 查询语句的执行方案确定下来,比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。
3、执行阶段
根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;

MySQL数据存放电脑位置

默认是在 /var/lib/mysql/ 目录里,一个xx数据库目录下有三个文件

db.opt, 用来存储当前数据库的默认字符集和字符校验规则。
xx.frm,用来存储结构,每建立一张表都会生成一个.frm 文件。
xx.ibd,用来存储数据,每一张表的数据都存放在一个独立的 .ibd 文件。

ibd文件结构

表空间由行、页、区、段组成。
1、行
数据库表中的记录都是按行进行存放的,每行记录根据不同的行格式,有不同的存储结构。
2、页
虽然记录是按照行来存储的,但是数据库的读取并不以行为单位,因为如果每次只能处理一行数据,效率会非常低。所以,InnoDB 的数据是以「页」为单位来读写的。每当需要读一条记录的时候,会把包含这条记录的整个页从磁盘读入内存。
页是 InnoDB 存储引擎磁盘管理的最小单元,它默认的大小是16KB,所以数据库每次读写都是以 16KB 为单位的。
3、区
4、段

行溢出是什么

MySQL 中磁盘和内存交互的基本单位是页,一个页的大小一般是 16KB,也就是 16384字节,而一个 varchar(n) 类型的列最多可以存储 65532字节,一些大对象如 TEXT、BLOB 可能存储更多的数据,这时一个页可能就存不了一条记录。这个时候就会发生行溢出,多的数据就会存到另外的「溢出页」中。

MySQL行记录存储格式

InnoDB 提供了 4 种行格式,分别是 Redundant、Compact、Dynamic和 Compressed 行格式。
1、Redundant
Redundant是MySQL5.0之前使用的格式,现在已经废弃了。
2、Compact
这个比较经典,后面的Dynamic和Compressed 都是基于Compact改造而来的。
在这里插入图片描述
在compact行格式下,一行记录分为两个部分:额外信息和真实数据。
额外信息
额外信息包含 3 个部分:变长字段的长度列表、NULL 值列表、记录头信息

变长字段的长度列表主要是存储变长字段所占用的数据大小,然后读取的时候可以根据这个长度列表来读取对应的数据长度。它在存储时是按照列的逆序来存放的。之所以要逆序,是因为记录头信息中指向下一个记录的指针,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。
如果表里没有变长字段,那行格式就不会有变长字段长度列表。

NULL 值列表:因为表中的某些列可能会存储 NULL 值,如果把这些 NULL 值都放到记录的真实数据中会比较浪费空间,所以 Compact 行格式把这些值为 NULL 的列存储到 NULL值列表中。如果列是NULL,那就给它对应值为1的二进制位。如果列值不是NULL,就给它一个0的二进制位。存放时也是逆序存放。
当数据表的字段都定义成 NOT NULL 的时候,这时候表里的行格式就不会有 NULL 值列表了。

记录头信息:包含比较多的东西,比如delete_mask 标识这条数据是否被删除。next_record下一条记录的位置等等。

真实数据
记录真实数据部分除了我们定义的字段,还有三个隐藏字段,分别为:row_id、trx_id、roll_pointer。
如果表里既没有指定主键,又没有唯一约束,那么 InnoDB 就会为记录添加 row_id 隐藏字段,占六个字节。
trx_id是事务id,表示这个数据是由哪个事务生成的,占6个字节。
roll_pointer,这条记录上一个版本的指针。roll_pointer 是必需的,占 7 个字节。

Dynamic
Compressed 和 Dynamic 这两个行格式和 Compact 非常类似,主要的区别在于处理行溢出数据时有些区别。
Compact 在行溢出时,会在记录的真实数据处只会保存该列的一部分数据,而把剩余的数据放在「溢出页」中,然后真实数据处用 20 字节存储指向溢出页的地址,从而可以找到剩余数据所在的页。
而Compressed 和 Dynamic 在行溢出时,记录的真实数据处只存储 20 个字节的指针来指向溢出页,而实际的数据全都存储在溢出页中。

索引

索引的定义就是帮助存储引擎快速获取数据的一种数据结构,形象的说索引就相当于数据的目录。

  • 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。
  • 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。
  • 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。
  • 按「字段个数」分类:单列索引、联合索引。

InnoDB 存储引擎会根据不同的场景选择不同的列作为索引,默认底层使用的数据结构就是B+Tree索引。
B+Tree 是一种多叉树,只在叶子节点中按主键顺序放真实数据,在非叶子节点中只放索引。每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息。
B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。
一张表只能有一个聚簇索引,那为了实现非主键字段的快速搜索,就引出了二级索引,它也是利用了 B+ 树的数据结构,但是二级索引的叶子节点存放的是主键值,不是实际数据。

主键索引的 B+Tree 和二级索引的 B+Tree 是有一定区别的
主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。查询时需要先获得主键值,再通过主键索引中的 B+Tree 树查询到对应的叶子节点来获取整行数据。这个过程叫「回表」,也就是说要查两个 B+Tree 才能查到数据。

为什么InnoDB选择B+树作为索引数据结构

1、B+Tree vs B Tree
B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据,所以 B+Tree 的单个节点的数据量更小,在相同的磁盘 I/O 次数下,就能查询更多的节点。

2、B+Tree vs 二叉树
对于有 N 个叶子节点的 B+Tree,其搜索复杂度为O(logdN),其中 d 表示节点允许的最大子节点个数为 d 个。在实际的应用当中,d 值是大于100的,这样就保证了即使数据达到千万级别,B+Tree 的高度依然维持在 3~4 层左右,也就是说一次数据查询操作只需要做 3~4 次的磁盘 I/O 操作就能查询到目标数据。
而二叉树的每个父节点的儿子节点个数只能是 2 个,意味着其搜索复杂度为 O(logN),这已经比 B+Tree 高出不少,因此二叉树检索到目标数据所经历的磁盘 I/O 次数要更多。

3、B+Tree vs Hash
Hash 在做等值查询的时候效率贼快,搜索复杂度为 O(1)。
但是 Hash 表不适合做范围查询,它更适合做等值的查询,这也是 B+Tree 索引要比 Hash 表索引有着更广泛的适用场景的原因。

什么时候需要创建索引

索引缺点
需要占用物理空间,索引数量越大,占用的空间就越大;
创建和维护索引要耗费时间,这种时间随着数据量的增加而增大;
索引会降低表增删改的效率,因为每次增删改索引,B+ 树为了维护索引有序性,都需要进行动态维护。

什么时候需要索引?
有经常用于 WHERE 查询条件的字段,这样能够提高整个表的查询速度,如果查询条件不是一个字段,可以建立联合索引。
字段有唯一性限制的,比如商品编码;
经常用于 GROUP BY 和 ORDER BY 的字段,这样在查询的时候就不需要再去做一次排序了,因为建立索引之后在 B+Tree 中的记录都是排序好的。

什么时候不需要创建索引?
表数据太少的时候,不需要创建索引;
经常更新的字段不用创建索引,因为如果索引字段频繁修改,那么维护 B+Tree的成本就会上升,会影响数据库性能的。
WHERE 条件,GROUP BY,ORDER BY 里用不到的字段,索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的,因为索引是会占用物理空间的。
字段中存在大量重复数据,比如性别字段,男女的记录分布均匀,那么无论搜索哪个值都可能得到一半的数据。这种情况MySQL很可能会通过查询优化器进行全表扫描。

优化索引方法

使用前缀索引
前缀索引顾名思义就是使用某个字段中字符串的前几个字符建立索引,比如在一些包含长字符串的字段上用它的前几个字符作为前缀索引,就可以减小索引字段大小,增加一个索引页中存储的索引值,有效提高索引的查询速度。

order by 无法使用前缀索引;
无法把前缀索引用作覆盖索引;

使用覆盖索引
覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。
所以我们可以针对要查询的字段建立一个联合索引,从而避免回表。

使用自增主键
InnoDB 创建主键索引默认为聚簇索引,数据存放在 B+Tree 的叶子节点上。同一个叶子节点内的各个数据是按主键顺序来存放的,每当有一条新的数据插入时,数据库会根据主键把其插入到对应的叶子节点中。
如果我们使用自增主键,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有的数据,当页面写满,就会自动开辟一个新页面。因为每次插入一条新记录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。
如果我们使用非自增主键,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其它数据来满足新数据的插入,甚至可能发生从一个页面复制数据到另外一个页面的页分裂情况。页分裂还有可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率。比如一个满的数据页里是1、3、5、9,现在要插入数据7,那就需要把这个页面分割成两个页面,一个是13、一个是579。如果是自增的主键插入就不会出现这种情况。

InnoDB内部怎么存储数据

首先,InnoDB 的数据是按「数据页」为单位来读写的,每个数据页的默认大小是 16KB。
在这里插入图片描述
在 文件头里有两个指针,分别指向上一个数据页和下一个数据页,这样相当于把所有的页连接成一个双向的链表。
数据页中的记录会按照「主键」顺序组成单向链表,这样插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索。所以,数据页中有一个页目录,起到记录的索引作用,这样就能快速找到所需的记录。

页目录创建过程
首先会把将所有的记录按主键顺序划分成若干个组,每个记录组的最后一条记录就是该组的最大记录,并且会在最后一条记录的头信息中存储这个组记录的总条数。然后用页目录来存储每组最后一条记录的地址偏移量,就相当于一个槽,每个槽指向了不同组的最后一个记录,槽相当于分组记录的索引。因为记录是按照「主键值」从小到大排序的,所以我们通过槽查找记录时,可以使用二分法快速定位要查询的记录在哪个槽里,定位到槽后,再遍历槽内的所有记录,找到对应的记录,无需从最小记录开始遍历整个页中的记录链表。

所以对一个数据页中的记录检索来说,因为一个数据页中的记录是有限的,且主键值是有序的,所以通过对所有记录进行分组,然后将组号(槽号)存储到页目录,使其起到索引作用,通过二分查找的方法快速检索到记录在哪个分组,来降低检索的时间复杂度。

B+ 树如何进行查询

当我们需要存储大量的记录时,就需要多个数据页,这时我们就需要考虑如何建立合适的索引,才能方便定位记录所在的页。
InnoDB 采用了 B+ 树作为索引底层结构,InnoDB 里 B+ 树中的每个节点都是一个数据页。
在这里插入图片描述
只有叶子节点才存放了数据,非叶子节点仅用来存放目录项作为索引。所有节点按照索引键大小排序,构成一个双向链表,便于范围查询;

比如要查找6
从根节点开始,通过二分法快速定位到符合页内范围包含查询值的页,因为查询的主键值为 6,在[1, 7)范围之间,所以到页 30 中查找更详细的目录项;
在非叶子节点(页30)中,继续通过二分法快速定位到符合页内范围包含查询值的页,主键值大于 5,所以就到叶子节点(页16)查找记录;
接着,在叶子节点(页16)中,通过槽查找记录时,使用二分法快速定位要查询的记录在哪个槽(哪个记录分组),定位到槽后,再遍历槽内的所有记录,找到主键为 6 的记录。

可以看到,在定位记录所在哪一个页时,也是通过二分法快速定位到包含该记录的页。定位到该页后,又会在该页内进行二分法快速定位记录所在的分组(槽号),最后在分组内进行遍历查找。

聚簇索引和二级索引

为什么MySQL要采用B+树作为索引底层结构呢?

首先,我讲一下B+树的前世今生。
我们都知道MySQL 的数据是需要持久化到磁盘上的。但是计算机从磁盘中读取数据的速度比较慢,当我们通过索引查找某行数据的时候,就需要先从磁盘读取索引到内存,再通过索引从磁盘中找到对应的数据然后读入到内存里,那么这个过程会发生多次磁盘 I/O,所消耗的时间也就比较大。所以,我们希望索引的数据结构能在尽可能少的磁盘的 I/O 操作中完成查询工作。所有我们希望这个查询的过程即要少的磁盘IO,又要高效执行范围查找。

1.0 线性查找

所以为了查找的高效率,我们在想索引数据按顺序排列,然后用二分查找法怎么样。因为二分查找每次都把查询的范围减半,这样时间复杂度就从挨个查找的n降到了 O(logn)。

2.0 二叉查找树

虽然线性排序使用起来比较简单,但是插入新元素的效率太低。因为每插入一个新元素,都要把这个元素之后的所有元素后移一位,如果这个操作发生在磁盘里面那这太夸张了,效率极低。而且每次查找都要不断计算中间的位置。所以我们想有没有一种非线形且适合二分查找的数据结构。

我们自然而然就想到了二叉查找树,二叉查找树的特点是每个节点左子树的所有节点都小于本节点,右子树的所有节点都大于本节点。这样我们在查询数据时,不需要计算中间节点的位置了,只需把要查找的数据和节点的数据进行比较就ok了。那这样不仅查找的效率变高了,在插入新节点时也不会像线性结构那样插入元素之后的元素都向后排列。

3.0 平衡二叉树

但二叉查找树就也不适合作为索引的数据结构,为什么呢,因为二叉查找树存在一个极端情况,如果每次插入的元素都是二叉查找树中最大的元素,那么这些元素就都会往右边排,这样二叉查找树就会退化成了一条链表,它查询的时间复杂度就又退化成了 O(n),而且随着树的高度越来越高,每次查询数据的时候磁盘 IO 次数就会越来越多,导致查询的性能严重下降。

为了解决二叉查找树会在极端情况下退化成链表的问题,后面就有人提出平衡二叉树的概念。
它主要是在二叉查找树的基础上增加了一些条件约束:每个节点左右子树的高度差不能超过 1。如果插入了元素之后导致节点左右子树高度差超过了1,那就自己维持平衡。比如往1节点的右子树是2,现在需要插入3,正常情况插入3的话还是在2子树的右边,那这就不平衡了,所以需要调整,原本1是中间节点,现在把2作为中间节点,1和3分别为2的左右子树,类似于这样的操作来维持平衡二叉树的自平衡状态。这样的话查询操作的时间复杂度就会一直维持在 O(logn) 。

4.0 B 树

但不管平衡二叉树还是有一定的缺点,因为随着插入的元素的增多,树的高度也会逐渐变高,这就意味着磁盘 I/O 操作次数多,会影响整体数据查询的效率。根本原因是因为它还是一个二叉树,它的每个节点只能保存 2 个子节点。所以我们在想,能不能树的每个节点可以有多个子节点,那这样树的高度不就下来了吗。

由此就引出了B树的概念,它不再限制每个节点只能有 2 个子节点,而是允许每个节点有 M 个子节点,以此来降低树的高度。这个M 称为 B 树的阶,所以 B 树的话它就是一个多叉树。所以相同数量的节点如果在B树的场景下,树的高度就会低很多,对应的磁盘 I/O 次数也会减少。

B+ 树

但是使用B树作为MySQL索引的结构又有了一些问题, 因为B 树的每个节点都会包含索引+记录,如果用户的记录数据的大小远远超过了索引数据的大小,那我们在查找需要的数据时就不得不从这部分数据上走过,这就需要花费更多的磁盘 I/O 操作次数来读到「有用的索引数据」。而且,当我们查询位于底层的某个节点时,其他不需要的记录数据也会从磁盘加载到内存,这样不仅增多磁盘 I/O 操作次数,也占用内存资源。

所以由此,最终的B+树概念就提出来了,B+树是对B树结构的一些改造,B+树只在叶子节点来存放实际数据索引+记录,而非叶子节点只会存放索引;所有索引也都会在叶子节点里保存一份,叶子节点之间构成一个有序链表;非叶子节点的索引也会同时存在在子节点中,并且是在子节点中所有索引的最大(或最小)。非叶子节点中有多少个子节点,就有多少个索引;
因为B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,所以在数据量相同的情况下,相比于既存索引又存记录的 B 树结构,B+树的非叶子节点可以存放更多的索引,所以 B+ 树的高度可以比 B 树更低,查询底层节点的磁盘 I/O次数会更少。而且在删除节点的时候,B+树可以直接从叶子节点中删除,这样删除非常快。
而且B+ 树所有叶子节点间还有一个链表进行连接,这种设计在进行范围查找时会更快,比如我们查 1-1 到 1-10 之间的订单,这个时候可以先查找到 1-1 所在的叶子节点,然后利用链表向右遍历,直到找到 1-10的节点,这样就不需要从根节点查询了,进一步节省查询需要的时间。

InnoDB里的B+树

然后Innodb 里使用的 B+ 树有一些特别的点,比如:
B+ 树的叶子节点之间是用「双向链表」进行连接,这样的好处是既能向右遍历,也能向左遍历。
B+ 树点节点内容是数据页,数据页里存放了用户的记录以及各种信息,每个数据页默认大小是 16 KB。

Innodb 根据索引类型不同,分为聚集和二级索引。他们区别在于,聚集索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚集索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据。
因为表的数据都是存放在聚集索引的叶子节点里,所以 InnoDB 存储引擎一定会为表创建一个聚集索引,且由于数据在物理上只会保存一份,所以聚簇索引只能有一个,而二级索引可以创建多个。

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

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

相关文章

【Spring Boot】Spring Boot项目的创建和文件配置

目录 一、为什么要学Spring Boot 1、Spring Boot的优点 二、创建Spring Boot项目 1、创建项目之前的准备工作 2、创建Spring Boot项目 3、项目目录的介绍 4、安装Spring Boot快速添加依赖的插件 5、在项目中写一个helloworld 三、Spring Boot的配置文件 1、配置文件的…

ELK 企业级日志分析系统(二)

目录 ELK Kiabana 部署(在 Node1 节点上操作) 1.安装 Kiabana 2.设置 Kibana 的主配置文件 3.启动 Kibana 服务 4.验证 Kibana 5.将 Apache 服务器的日志(访问的、错误的&#x…

知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例,Neo4j图算法是一套在Neo4j图数据库上运行的算法集合。这些算法专门针对图数据结构进行设计,用于分析、查询和处理图数据。图算法可以帮助我们发现图中的模…

【Azure】office365邮箱测试的邮箱账号因频繁连接邮箱服务器而被限制连接 引起邮箱显示异常

azure微软office365邮箱会对频繁连接自身邮箱服务器的IP地址进行,连接邮箱服务器IP限制,也就是黑名单,释放时间不确定,但至少一天及以上。 解决办法,换一个IP,或者新注册一个office365邮箱再重试。 以下是…

使用 API Gateway Integrator 在 Quarkus 中实施适用于 AWS Lambda 的 OpenAPI

AWS API Gateway 集成使得使用符合 OpenAPI 标准的 Lambda Function 轻松实现 REST API。 关于开放API 它是一个 允许以标准方式描述 REST API 的规范。 OpenAPI规范 (OAS) 为 REST API 定义了与编程语言无关的标准接口描述。这使得人类和计算机都可以发现和理解服务的功能&am…

中介者模式(C++)

定义 用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显式的相互引用(编译时依赖->运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互。 应用场景 在软件构建过程中,经常会出现多个对象…

漫画算法做题笔记

诸神缄默不语-个人CSDN博文目录 哦这是我三年前写的,我现在Java语法都快忘光了…… 反正之前的博文也发一下好了。这个因为我当年是用有道云笔记而不是直接用CSDN编辑器写的,所以后面有些内容写乱了,因为我现在猛的一看有点看不懂&#xff0…

C++11之右值引用

C11之右值引用 传统的C语法中就有引用的语法,而C11中新增了的 右值引用(rvalue reference)语法特性,所以从现在开始我们之前学习的引用就叫做左值引用(lvalue reference)。无论左值引用还是右值引用&#…

【TypeScript】初识TypeScript和变量类型介绍

TypeScript 1,TypeScript是什么?2,类型的缺失带来的影响3,Ts搭建环境-本博主有专门的文章专说明这个4,使用tsc对ts文件进行编译5,TS运行初体验简化Ts运行步骤解决方案1解决方案2(常见) 开始学习…

Apache Paimon 学习笔记

本博客对应于 B 站尚硅谷教学视频 尚硅谷大数据Apache Paimon教程(流式数据湖平台),为视频对应笔记的相关整理。 1 概述 1.1 简介 Flink 社区希望能够将 Flink 的 Streaming 实时计算能力和 Lakehouse 新架构优势进一步结合,推…

Centos更换网卡名称为eth0

Centos更换网卡名称为eth0 已安装好系统后需要修改网卡名称为eth0 编辑配置文件将ens33信息替换为eth0,可在vim命令模式输入%s/ens33/eth0/g替换相关内容 修改内核文件,添加内容:net.ifnames=0 biosdevname=0 [root@nova3 ~]# vim /etc/default/grub 使用命令重新生成g…

【JAVA】有关时间的操作在编程中如何实现?

个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 文章目录 前言Date 类Date 类方法Data的缺陷实例获取当前日期时间日期比较java中设置date数据的显示格式 前言 在许多应用程序中,日期和时间的处理是必不可少的。Java提供了一…

用Shap-E生成3D模型

Shap-E 是 OpenAI 开发的突破性模型,它使用文本或图像作为输入生成一系列 3D 对象,以其创新方法改变了 3D 应用领域。 这项非凡的技术可以在 GitHub 上免费获取,允许用户在计算机上无缝运行它,而无需 OpenAI API 密钥或互联网连接…

2023华数杯数学建模C题思路分析 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一,她不仅为婴儿提供营养物质和身体保护, 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况,如抑郁、焦虑、 压力等,可能会对婴儿的认知、情…

桌面端UI自动化测试如何让SplitButtonControl展开

原始SplitButtonControl图 从图中鼠标所指的控件属性为: ControlType(控件类型): SplitButtonControl ClassName(类名): SplitButton AutomationId(自动化ID): esri_geoprocessing_Pyt…

【Go】Go数据操作 - 处理JSON文件

目录 何为JSON 编码JSON 实践时刻 解码JSON 实践时刻 延伸拓展 何为JSON JSON (JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。JSON最初是 JavaScript的一部分,后由于便于快速编写的特性,被开发者独立出来。基本上所有的…

灵活利用ChatAI,减轻工作任务—语言/翻译篇

前言 ChatAI在语言和翻译方面具有重要作用。它能够帮助用户进行多语言交流、纠正错误、学习新语言、了解不同文化背景,并提供文本翻译与校对等功能。通过与ChatAI互动,我们能够更好地利用技术来拓展自己在语言领域的能力和知识,实现更加无障…

React Dva 操作models中的subscriptions讲述监听

接下来 我们来看一个models的属性 之前没有讲到的subscriptions 我们可以在自己有引入的任意一个models文件中这样写 subscriptions: {setup({ dispatch, history }) {console.log(dispatch);}, },这样 一进来 这个位置就会触发 这里 我们可以写多个 subscriptions: {setup…

编写简单的.gitlab-ci.yml打包部署项目

服务器说明: 192.168.192.120:项目服务器 192.168.192.121:GitLab 为了可以使用gitlab的cicd功能,我们需要先安装GitLab Runner 安装GitLab Runner参考: GitLab实现CICD自动化部署_gitlab cidi_程序员xiaoQ的博客-CS…