深入理解索引B+树的基本原理

目录

1. 引言

2. 为什么要使用索引?

3. 索引的概述

4. 索引的优点是什么?

4.1 降低数据库的IO成本,提高数据查找效率

4.2 保证数据库每一行数据的唯一性

4.3 加速表与表之间的连接

4.4 减少查询中分组与排序的执行时间

 5. 索引的缺点是什么?

5.1 创建索引和维护索引非常耗费时间

5.2 索引也是占用磁盘空间的

5.3 索引会降低表的更新速度

6. B+ 树到底是什么样的?

7. 数据库底层存储数据的实质

8. 索引的实现原理

9. 为什么B+树的高度不建议超过四层?

10. 什么是聚簇索引?

10.1 聚簇索引的特点

10.2 聚簇索引的优点?

10.3 聚簇索引的缺点?

10.4 聚簇索引的补充说明

11. 什么是非聚簇索引?

12. 什么是回表?

13. 为什么非聚簇索引的叶子节点不存储一份完整的数据方便查找呢?

14. 聚簇索引与非聚簇索引的区别?

15. 什么是联合索引?


1. 引言

我们知道,只要谈起数据库,索引重中之重,不管你是面试开发程序员,架构师,甚至是校园招聘,你会发现几乎都问到了索引。那么它到底是个什么东西?竟能如此重要。它到底有什么好处呢?为什么面试的时候总喜欢问索引呢?它的底层实现是什么样的呢?今天我们就一同来揭晓这些问题的答案。

提前声明,想要更加透彻深入的学会索引,建议你对数据结构有很好的了解,特别是树和链表,如果你对树这种结构很清晰,那么学会索引非常轻松,如果不会,也没关系,并没有很大影响。

2. 为什么要使用索引?

想要理解索引,我们首先要知道为什么要使用索引。

我来说一个场景,假设现在我的一张用户表中有十万条用户数据,用户 id 唯一,我想要查询id 位80000的用户信息,那么数据库是靠什么快速的在十万条数据中找到这条id为80000的用户数据的呢?各位有没有想过这个问题?

其实底层就是索引在帮忙,做一个简单的比喻,如果我们把刚才的用户表中的数据存放到一本字典中,那么索引就是这个字典的目录,当我们想要查找某一个数据的时候,数据库底层不会傻乎乎的去一页一页从字典中翻找我们想要的数据,而是直接去翻这根本字典的目录,通过目录精准定位我们想要查询的数据在哪一页,然后直接定位到那一页,将我们要查找的数据取出。

那么各位再想一下,如果字典没有目录。会是什么样的结果呢?我们要查找用户张三的信息,然后数据库受到了指令,从第一页开始翻看查阅,没有翻到第二页,有没有翻到第三页......各位想过没有,这会多麻烦,所以,通过字典目录提高查找效率是必须要做的,通过索引查找数据也是迫在眉睫的,但同样,我们既然制造了目录,如果我们对字典中的数据做了更改,目录是不是也要改啊,这就为我们后续索引的缺点做了铺垫。

总结来说就一句话,之所以要使用索引,是因为索引可以提高我们查找数据的效率。

3. 索引的概述

MySQL官方给索引的定义是:索引(Index)是帮助MySQL高效获取数据的数据结构。

简洁点来说,索引的本质是数据结构。

此外,索引是在存储引擎中实现的,当我们的存储引擎不同时,索引底层的数据结构也不相同。

同时,存储引擎中还定义了一个表中最多不能超过16个索引,但其实我们也用不到这么多,所以完全可以放心;也定义了索引的长度不能超过256个字节,其实也很大了,我们通常不会把索引定义那么大,也可以放心。

4. 索引的优点是什么?

4.1 降低数据库的IO成本,提高数据查找效率

各位细想,我们的数据都是存储在磁盘上的,只有我们在需要的时候才会从磁盘IO读取到内存中。那么用户表的那本字典,如果没有索引,我会就会先从磁盘IO加载第一页的数据到内存,然后遍历数据,发现没有找到,再经过IO磁盘,加载第二页的数据到内存,再遍历查找...... 各位知道,内存中数据的处理速度是很快的,但是从磁盘加载到内存这个速度就很慢了,假设我们遍历一页数据需要1ms,那么IO一次可能就需要50ms,这还只是加载了第一页的数据,那如果有很多很多页数据,查找速率绝对非常慢。但是如果我们使用了索引,我们只需要IO一次将索引加载到内存中,遍历索引,精准找到数据所在的页数,然后第二次IO直接读取是数据所在的那一页数据,这样的话,只需要经过两次磁盘IO就可以得到我们需要的数据了。

4.2 保证数据库每一行数据的唯一性

我们知道,表中通常都是有主见的,而且都会设置为非空且唯一,我们的索引也是一样,索引也是具有唯一性的,通过创建唯一索引,可以保证数据库表中每一行数据的唯一性。

4.3 加速表与表之间的连接

对于有父子关系的子表与父表在进行联合查询时,索引可以加速表与表之间的连接,从而提高表的查询效率。

4.4 减少查询中分组与排序的执行时间

各位想一下,字典中的目录我们都是按照一定的规律去进行排列的,索引也是一样的道理,从小到大把数据进行排列,既然是已经排好序的数据了,当我们在查询语句中对数据进行ORDER BY 排序时候,其实已经是有序的了,那么就省去了我们再次排序的时间,而且以后查询排序都不需要浪费时间,是一个一劳永逸的做法。

 5. 索引的缺点是什么?

5.1 创建索引和维护索引非常耗费时间

这一点我想不难理解,各位想,当我们对一本书中的内容做了更改之后,你是不是也要去更改目录啊,特别是你的书内容如果不较多,如果你删除了几页内容,其他的内容都要跟着做调整;如果你一直往书中继续写内容,目录也要跟着增多吧,所以说,索引的创建与维护也是非常浪费时间的。

5.2 索引也是占用磁盘空间的

则会就好比是一本书,你书中的内容需要用纸张去些内容,那么目录也要写在纸上啊;而且索引本身就是数据结构,是需要占用磁盘的空间的,并且随着你数据量的增大,你索引所占的磁盘空间大小很有可能会超过数据本身所占的磁盘文件大小。

5.3 索引会降低表的更新速度

其实这一点与维护索引是有一些内在关联的,如果我们对表中的数据做了动态修改,那么索引也是会不断地去动态修改维护的,这就大大的降低了表的更新速度。

6. B+ 树到底是什么样的?

我们知道,数据结构中有一种数据结构叫做树,我们最常见的就是二叉树,还是平衡二叉树,还有二叉树的升级版红黑树。

既然有二叉树,就有三叉树,N叉树。

其实,B+树底层就是一个N叉树,这里我以三叉树为例,模型如下图所示

我们的对顶层就是根节点,中间层是子节点,最下层是叶子节点。

在数据库底层 InnoDB 存储引擎中,存储数据和索引就是采用B+树的形式存储的。

7. 数据库底层存储数据的实质

如上图所示,是我们数据库中常见的一张表,这里有很多的数据,但是在底层,你们知道吗,表的每一行数据都是单独存储的,在磁盘上的存储位置是不连续的。因为如果我们表中的数据有很多,达到了上万条数据,那么在磁盘中不一定有那么大的一个连续空间,因此在数据库底层,它的每一行数据都是单独存储的,而且还要满足一个逻辑上的连续,我们 employee_id = 100 的员工下一条记录是 employee_id = 101 的员工这一点是不能变的,不能说我查一次,它们的顺序就变一次,一定要它们保持一定的逻辑连续性。

说到这里各位应该就明白了吧,没错!就是链表,其实表中的每一行数据在磁盘底层是采用单向链表的形式来存储的,这样不仅解决了存储空间大小不够问题,还解决了让它们在逻辑上满足连续性的问题。

就拿上面这张表举例,在数据库的底层,employee_id = 100 的员工就是链表的头节点,它内部还会存储 employee_id = 101 的员工的地址值,从而找到该员工的全部相关信息,而employee_id = 101 的员工内部也会存储 employee_id = 102 的员工的地址值,通过该地址值找到 employee_id = 102 的员工全部信息由此形成一个单向链表。

8. 索引的实现原理

如上图,根据上面B+树的结构,我们就能大致推演出索引的底层原理了,这里我化繁为简,简单说明。

我们先看最下层,最下层也是叶子节点页,这些叶子节点页之间是使用双向链表进行连接的,而内部的数据则是我刚刚说的通过单向链表连接的,图中已经标识出,而且每一页中都有一个数组,存放主键的值,方便我们后续使用二分法快速确定要查找的数据。在B+树索引中,所有的真实数据都是存放在叶子节点叶中的,如图,在叶子节点中页10中,下方的 1,4,u;3,9,d;4,4,a 就是一条条真实的数据,上方的0就是指这些是数据,假设1,3,4这些首字段为一条条数据的主键。

我们继续推演,如果没有中间层页30与页32,只有最下方一层,当我们想要找想要查找主键为100的用户信息时,就需要从页10开始从头遍历这个双向链表,在遍历到页9的时候,找到了主键为100的用户,我们直接获取到该用户的信息,一共遍历了3页,需要进行三次磁盘IO。

如果我们加上中间层,为每一个叶子节点页再创建一个目录,即页30与页32,页30下方存储了1,10;5,28;12,9;209,20四条数据。这里的1,10中的1指代的就是叶子节点页10中最小的一条数据1,10则是指代页10,实际存储的是页10的内存地址;5,28则是叶子节点页28中的最小主键值5与该页所在的地址值,这些数据上方都是1,表示他们仍然是目录页而不是真实的数据...... 我们使用了这个中间目录页之后,我们再去获取主键为100的用户数据时,就会先去遍历中间页,在中间页中确定主键值为100的用户数据存放在页9中,就可以直接将页9中的数据全部读取到内存,然后再去寻找该用户的数据,可以发现,此时加上了中间页之后,只需要两次IO,节约了时间,提高了查找效率。

我们继续类比推理,如果以后我的数据越来越多,中间也最多只能存放四个叶子节点页的数据,再多就存不下了,这个时候,我们就需要继续创建新的中间页,而如果中间页一直增多,就会面临和刚才叶子节点页一样的问题。

这个时候,我们就可以套娃式的去再创建一个中间页的顶层也,让这个顶层页使用类似的手段存放中间页的重要数据。举例说明,我们想要查找主键为300的用户数据,第一次磁盘IO,我们把页33的全部数据加载到内存中,经过二分查找判断发现与主键为300的用户数据应存放在子页30中,在然后进行第二次IO,将子夜30的全部数据加载到内存中,再经过二分查找判断,确定主键为300的用户数据存应放在叶子节点页20中,在进行第三次磁盘IO,将叶子节点页20中的数据全部加载到内存中,再经过二分查找,快速定位到主键为300的用户所在的内存地址,获取到信息,此时只需要经历三次磁盘IO,而且非常稳定,当我们想要查询某条数据是,都是进行三次磁盘IO就可以获取到结果,找得到或找不到都要返回,极大的保证了我们查找数据时的稳定性。

9. 为什么B+树的高度不建议超过四层?

在刚才我举得例子中,各位应该看得出来,我所举例的B+树是三层,绝大多数情况下都是三层,最多四层。而在面试的时候,有些面试官会问你为什么B+树的不建议超过四层,请给出具体的原因。

原因如下:

不知道各位发现了没有,当我们的B+树只有两层时,我们最多就可以经过两次磁盘IO就可以查找到数据,当B+树是三层时,我们进行三次磁盘IO就可以获取到数据。这也从侧面印证了一点,我们与磁盘交互的次数,是受到B+树高度的影响的,各位都知道,内存中处理数据速度是非常快的,二分查找数据可能就1ms~3ms左右的时间,而与磁盘IO就不一样了,磁盘IO一次可能就需要花费100ms,每交互一次100ms,这个效率是非常低的,因此我们应当尽量减少与磁盘的IO次数,这就要求我们B+树的高度不能过高,最好三层,不能超过四层。

那肯定会有人问,问什么非要是三层或四层,我选五层不行吗?

其实从原则上来讲也是可以的,但是我们还要考虑数据的存储量,这里给各位说一下,数据库的底层一个真实的数据页大小是16KB,也就是 16000 个字节,假设我们的每条数据占用160个字节,160个字节已经不小了,完全够用,那么我们每个叶子节点页就可以存储 16000/160 = 100 条数据。而我们的非叶子节点页,因为并没有存储真实的用户数据,所以可以存储更多的内容,假设我们的目录页可以存储 1000 条叶子节点页数据,当我们的B+树正好满两层的时候,存储的数据量是 100 * 1000 = 100,000 十万条数据;当我们 B+ 树满两层时,存储的数据量是 100 * 1000 * 1000 = 100,000,000 一亿条数据;让我们的B+树满5层时,存储的数据量是 100 * 1000 * 1000 * 1000 = 100,000,000,000 一千亿条数据,可以看到,当B+树5层的时候,数据量已经非常恐怖了,而且我们也不可能在一张表中存储这么多数据。

而在实际开发业务的时候,我们会采用微服务的架构,并对数据库进行分库分表,进行读写分离,不会让大量数据在同一张表中存储,既不安全,效率又低。因此,我们通常会把B+树控制在三层左右,此时一张表就足以存储一亿条数据,而且只需要三次磁盘IO就可以查找到想要的数据,综合考虑是最优的选择。如果像阿里京东腾讯这些用户量多余1亿的企业,也有可能会采用四层B+树,但其实还是是很少这么做的。这就是为什么要把B+树的高低控制在四层以下,总的来说就一句话,三层或四层B+树,既满足了数据量的存储需要,又达到了最佳查找效率。

10. 什么是聚簇索引?

聚簇索引,又名主键索引,它是基于表的主键而生成的索引,而且它不是一种索引的类型,而是一种数据的存储方式(表中所有的用户数据都会存放在叶子节点中)如下图所示就是一个经典的聚簇索引。在 InnoDB 引擎中,聚簇索引是不需要我们手动创建的,在我们创建好表结构的时候,数据库的底层已经为我们生成聚簇索引,并随着我们数据的添加,索引会一直不断的变化和维护。

10.1 聚簇索引的特点

聚簇索引还有一些特点,只有满足以下四点的索引才能称为聚簇索引:

1. 每个页内的记录是按照的主键的大小顺序形成的一个单向链表,例如页10中的(1,4,u)与(3,9,d)便是通过单向链表连接的;

2. 各个存放的数据页之间采用的是双向链表进行连接,如图中的页10与页28之间就是双向链表;

3. 存放目录项记录的页(即刚才我所提的中间层)它们之间也是采用双向链表的形式进行连接,如图中的页30与页32就是双向链表;

4. B+ 树中存放的是完整的表数据,如图中页10的(1,4,u),(3,9,d)等,这里我列的简单,只有三个字段,实际聚簇索引存储的数据会以你定义的表中的字段为主;

10.2 聚簇索引的优点?

(1)因为聚簇索引中将索引与所有的表数据都存储在了B+树种,所以聚簇索引比非聚簇索引查询效率要高

(2)因为聚簇索引是基于主键大小排列的索引,所以对于主键的范围查找与排序查找速度非常快

(3)因为聚簇索是引按照一定的顺序进行排列,再查询显示一定范围的数据的时候,由于数据是紧密相连的,数据库就不需要从不同的区块中去提取数据,节省了大量的IO操作

10.3 聚簇索引的缺点?

(1)插入的速度严重依赖于插入的顺序。因为聚簇索引是按照逐渐的顺序去建立的,如果我们不按照顺序去插入,而是突然插入一个主键值大的数据,又突然插入一个主键值小的数据,这就会导致索引会不断地去动态变化,还可能出现页分裂,严重影响性能,因此对于 InnoDB 引擎来说,建议在插入数据的时候按照顺序插入或者使用主键自增策略。

(2)更新主键的代价极高。因为聚簇索引就是基于几件生成的,如果我们对主键做出更改,那么整个索引结构可能都要进行更改,而进行更改是非常耗费性能的,因此对于 InnoDB 引擎来说,我们一般最好把主键定义为不可更改。

10.4 聚簇索引的补充说明

(1)MySQL 数据库目前只有 InnoDB 引擎支持聚簇索引,MyISAM 引擎不支持聚簇索引;

(2)由于数据物理存储排序方式只有一种,所以每个 MySQL 表只能有一个聚簇索引,一般情况下都是该表的主键;

(3)如果我们没有给表定义主键,那么 InnoDB 会选择一个非空且唯一的字段替代,如果也没有这样的字段,那么 InnoDB 会隐世式定义一个主键作为聚簇索引;

(4)为了充分利用聚簇索引的特性, InnoDB 引擎下在定义表的主键的时候,不建议使用无序的id,例如UUID,MD5,HASH,字符串等作为主键,否则无法保证数据的顺序增长。

11. 什么是非聚簇索引?

非聚簇索引,也可以叫二级索引,或叫辅助索引。

刚才我们说到了,聚簇索引是 InnoDB 引擎基于主键自动生成的,可以提高有关主键的查找速度和查找范围,也就是说只有搜索条件中包含主键字段时才有效果。那么当我们不使用主键字段来查找数据而是基于普通字段查找数据同时又想提高查找效率的时候,我们就可以通过普通字段定义非聚簇索引。如下图所示就是一个非聚簇索引所构成的 B+ 树。

这里需要注意一点,非聚簇索引构成的 B+ 树与聚簇索引构成的 B+ 树稍有不同。

这里目录页44与子目录页42,43的原理与聚簇索引中类似,但叶子节点中就不一样了,刚才我说到了,聚簇索引中,存放着完整的表数据,而在非聚簇索引中,叶子节点中只存放着索引对应的那个普通字段与主键值。如图中,蓝色对应的就是普通字段,黄色对应的就是主键值,我们可以看一下,在前面那张图中,页9中存放这一条数据(20,2,e),正好对应着我们这里的非聚簇索引,这里页34下面蓝色方块中值为2的数据对应的主键值也为20,这样说各位同学应该更好理解一些,各位可以将上图与前面聚簇索引中的字段值做对比就可以看出来,我就不一一举例说明了。

12. 什么是回表?

刚才我说到了,在非聚簇索引中,叶子节点只存放了该索引字段的相关信息和主键信息,那么只有这两项信息肯定是不够的,如果我们的目的是通过非聚簇索引查询某条用户的全部信息,它就会进行回表操作,什么是回表呢?

其实很简单,当我们使用非聚簇索引的字段作为查询条件去查询表中的相关信息时,数据库会先根据非聚簇索引形成的 B+ 树,一步步查找到与查询条件相关的信息,再根据它们各自对应的主键去聚簇索引中查询完整的用户信息,这个过程中,需要先查询非聚簇索引的 B+ 树,再去查询聚簇索引的 B+ 树,查询之后又回去再查了一次表,这个过程就叫做回表。

举个栗子,现在有一张表 user ,主键 uid ,手机号码 phone,用户名 username,密码 password四个字段,我们给手机号码字段创建了非聚簇索引,那么它的底层就会只存储手机号码信息和所对应的主键uid 信息,当我们通过 手机号去查询用户完整信息时,语句应该是 SELECT * FROM user WHERE phone = "待查询用户手机号";在这个查询语句中,它会先去非聚簇索引形成的 B+ 树通过 phone 查找到对应的主键uid,查找到主键uid的信息之后,它会再去聚簇索引的 B+ 树中通过 uid 查询出完整的用户信息并返回,这就是它在底层的执行逻辑,先查非聚簇索引,再回表查聚簇索引。

13. 为什么非聚簇索引的叶子节点不存储一份完整的数据方便查找呢?

这个问题其实也算是一个面试题。我刚才说了什么是回表,但是不知道各位发现一个问题没有,回表还需要再查寻一次 B+ 树,这样不是很麻烦吗?我们直接将用户的全部信息在非聚簇索引的 B+ 树中叶存储一份多省事啊,怎么不这样做呢?

如果你也有这样的问题,说明你认真思考了。大家想一想,在聚簇索引中,我们已经存储了一份完整的表数据,还有 B+ 树的结构,这些都是非常占用磁盘满空间的,而非聚簇索引又不止可以创建一个,我们可以创建多个,刚才我举的例子中只有四个字段,在实际的业务场景中,二十个字段也是很有可能的,如果我们为了方便查找又创建了三个非聚簇索引,并且图方便在非聚簇索引中也存储完整的用户数据,各位同学想一想,这样是不是非常冗余,我们的用户数据明明存储一份就够了,但是你创建一个非聚簇索引,数据就多存储一份,再创建一个,再存储一份,我们创建三个非聚簇索引,那么加上聚簇索引我们底层的数据足足存储了四份,非常非常冗余,这是绝对不允许的。另外,如果我们把全部的数据都存在非聚簇索引中,那么当我们要对用户数据作出修改时,有多少个索引,我们就要修改多少次,各位想是不是,我们对用户张三做修改,所有的索引中关于张三的信息都要做修改,非常不划算不值得。所以不在非聚簇索引上也存储一份完整的用户数据,一方面是为了防止数据大量冗余,造成磁盘资源的浪费;另一方面是防止多余的操作。

14. 聚簇索引与非聚簇索引的区别?

(1)聚簇索引叶子节点存储的是完整的用户数据,而非聚簇索引中存储的只有主键与索引字段数据,非聚簇索引不会影响表的物理存储结构;

(2)一个表只能有一个聚簇索引,但是可以有多个非聚簇索引;

(3)使用聚簇索引时,查询效率很高,但如果是对数据进行增删改操作,效率会比非聚簇索引低;

15. 什么是联合索引?

说的准确一些,联合索引其实属于是非聚簇索引中的一种,它与我们说的联合主键是有一些类似的,刚才我们说的非聚簇索引是使用一个字段构成 B+ 树,而有些时候我们会把数据库中的两个字段都作为索引,这种情况下形成的索引就叫联合索引。

举个例子,假设一张学生表 student ,有主键字段C1,非主键字段C2,C3,C4,C5。现在我们为C2与C3创建联合索引,那么形成的 B+ 树中就会存放 C2,C3,C1字段,并按照从上到下的顺序排列,会先比较联合字段C2的大小,先按C2大小排序,当C2大小相同时,再根据C3大小排序,在下方存贮主键C1的值,从而形成一个联合索引 B+ 树。

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

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

相关文章

[足式机器人]Part3机构运动微分几何学分析与综合Ch03-1 空间约束曲线与约束曲面微分几何学——【读书笔记】

本文仅供学习使用 本文参考: 《机构运动微分几何学分析与综合》-王德伦、汪伟 《微分几何》吴大任 Ch01-4 平面运动微分几何学 3.1 空间曲线微分几何学概述3.1.1 矢量表示3.1.2 Frenet标架 连杆机构中的连杆与连架杆构成运动副,该运动副元素的特征点或特…

【Stable Diffusion】雨天、湿身

一、Models 1.1、Wet Clothes (Clothing Style) [LoHA] WECL SEE-THROUGH WET WET HAIR BIKINI OR SWIMSUIT UNDER CLOTHES NO BRA BRA VISIBLE THROUGH CLOTHES MISC SHIRTS MISC CLOTHES1.2、Rain 雨 Multiply Style rain style1.3、Wet T-Shirt LORA <lora:wetshirt:…

5.1 web浏览安全

数据参考&#xff1a;CISP官方 目录 Web应用基础浏览器所面临的安全威胁养成良好的Web浏览安全意识如何安全使用浏览器 一、Web应用基础 1、Web应用的基本概念 Web ( World wide Web) 也称为万维网 脱离单机Web应用在互联网上占据了及其重要的地位Web应用的发展&#xf…

最新Kali Linux安装教程:从零开始打造网络安全之旅

Kali Linux&#xff0c;全称为Kali Linux Distribution&#xff0c;是一个操作系统(2013-03-13诞生)&#xff0c;是一款基于Debian的Linux发行版&#xff0c;基于包含了约600个安全工具&#xff0c;省去了繁琐的安装、编译、配置、更新步骤&#xff0c;为所有工具运行提供了一个…

计算机竞赛 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

【量化课程】02_4.数理统计的基本概念

2.4_数理统计的基本概念 数理统计思维导图 更多详细内容见notebook 1.基本概念 总体&#xff1a;研究对象的全体&#xff0c;它是一个随机变量&#xff0c;用 X X X表示。 个体&#xff1a;组成总体的每个基本元素。 简单随机样本&#xff1a;来自总体 X X X的 n n n个相互…

梯度下降介绍

什么是梯度 梯度是微积分中一个很重要的概念&#xff0c;在单变量的函数中&#xff0c;梯度其实就是函数的微分&#xff0c;代表着函数在某个给定点的切线的斜率&#xff1b;在多变量函数中&#xff0c;梯度是一个向量&#xff0c;向量有方向&#xff0c;梯度的方向就指出了函…

809协议nodejs编写笔记(还在更新)

一、总体流程 数据首先通过receiver接受层接收&#xff0c;去掉标识头和标识尾&#xff1b;再进入depacker解包层进行解包&#xff0c;把标识头分解出来并解析&#xff1b;之后发给handler处理层根据不同的消息id选择使用不同的业务逻辑&#xff1b;如果有应答&#xff0c;则通…

陪诊小程序开发|陪诊陪护小程序让看病不再难

陪诊小程序通过与医疗机构的合作&#xff0c;整合了医疗资源&#xff0c;让用户能够更加方便地获得专业医疗服务。用户不再需要面对繁琐的挂号排队&#xff0c;只需通过小程序预约服务&#xff0c;便能够享受到合适的医疗资源。这使得用户的就医过程变得简单高效&#xff0c;并…

CSS中的position属性有哪些值,并分别描述它们的作用。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ static⭐ relative⭐ absolute⭐ fixed⭐ sticky⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那…

Tomcat多实例部署及nginx+tomcat的负载均衡和动静分离

Tomcat多实例部署 安装 jdk、tomcat&#xff08;流程可看之前博客&#xff09; 配置 tomcat 环境变量 [rootlocalhost ~]# vim /etc/profile.d/tomcat.sh#tomcat1 export CATALINA_HOME1/usr/local/tomcat/tomcat1 export CATALINA_BASE1/usr/local/tomcat/tomcat1 export T…

pdf怎么转换成jpg图片?这几个转换方法了解一下

pdf怎么转换成jpg图片&#xff1f;转换PDF文件为JPG图片格式在现代工作中是非常常见的需求&#xff0c;比如将PDF文件中的图表、表格或者图片转换为JPG格式后使用在PPT演示、网页设计等场景中。 【迅捷PDF转换器】是一款非常实用的工具&#xff0c;可以将PDF文件转换成多种不同…

HTML详解连载(5)

HTML详解连载&#xff08;5&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽行高&#xff1a;设置多行文本的间距属性名属性值行高的测量方法 行高-垂直居中技巧 字体族属性名属性值示例扩展 font 复合属性使用场景复合属性示例注意 文本缩进属性…

YOLO v8目标跟踪详细解读(二)

上一篇&#xff0c;结合代码&#xff0c;我们详细的介绍了YOLOV8目标跟踪的Pipeline。大家应该对跟踪的流程有了大致的了解&#xff0c;下面我们将对跟踪中出现的卡尔曼滤波进行解读。 1.卡尔曼滤波器介绍 卡尔曼滤波&#xff08;kalman Filtering&#xff09;是一种利用线性…

Python学习 -- 常用函数与实例详解

在Python编程中&#xff0c;数据转换是一项关键任务&#xff0c;它允许我们在不同数据类型之间自由流动&#xff0c;从而提高代码的灵活性和效率。本篇博客将深入探讨常用的数据转换函数&#xff0c;并通过实际案例为你展示如何巧妙地在不同数据类型之间转换。 数据类型转换函…

分布式监控平台——Zabbix

市场上常用的监控软件&#xff1a; 传统运维&#xff1a;zabbix、 Nagios 一、zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监…

【数学建模】--因子分析模型

因子分析有斯皮尔曼在1904年首次提出&#xff0c;其在某种程度上可以被看成时主成分分析的推广和扩展。 因子分析法通过研究变量间的相关稀疏矩阵&#xff0c;把这些变量间错综复杂的关系归结成少数几个综合因子&#xff0c;由于归结出的因子个数少于原始变量的个数&#xff0c…

【第三讲-三维空间刚体运动】

旋转矩阵 点、向量、坐标系 坐标系分为左左手系和右手系 下面讨论有关向量的运算&#xff1a; 内积 外积&#xff1a; 外积的结果是一个向量&#xff0c;方向垂直于这两个向量&#xff0c;大小为

sift-1M数据集的读取及ES插入数据

sift是检查ann近邻召回率的标准数据集,ann可以选择faiss,milvus等库或者方法;sift数据分为query和base,以及label(groundtruth)数据。本文采用sift-1M进行解读,且看如下: 1、sift-1m数据集 官方链接地址:Evaluation of Approximate nearest neighbors: large datase…

brew+nginx配置静态文件服务器

背景 一下子闲下来了&#xff0c;了解的我的人都知道我闲不下来。于是&#xff0c;我在思考COS之后&#xff0c;决定自己整一个本地的OSS&#xff0c;实现静态文件的访问。那么&#xff0c;首屈一指的就是我很熟的nginx。也算是个小复习吧&#xff0c;复习一下nginx代理静态文…