伊人成色综合人夜夜久久
你的位置:伊人成色综合人夜夜久久 > 人妻无码 > 换一个角度看 B+ 树
换一个角度看 B+ 树
发布日期:2022-06-18 17:08    点击次数:164

换一个角度看 B+ 树

本文转载自微信公众号「小林coding」,作家小林coding 。转载本文请干系小林coding公众号。

各人好,我是小林。

各人背八股文的时候,都泄漏 MySQL 里 InnoDB 存储引擎是选用 B+ 树来组织数据的。

这点没错,然而各人泄漏 B+ 树里的节点里存放的是什么呢?查询数据的历程又是如何的?

此次,咱们从数据页的角度看 B+ 树,望望每个节点长啥样。

InnoDB 是如何存储数据的?

MySQL 复古多种存储引擎,不同的存储引擎,存储数据的形态亦然不同的,咱们最常使用的是 InnoDB 存储引擎,是以就跟各人图解下InnoDB 是如何存储数据的。

记载是按照行来存储的,然而数据库的读取并不以「行」为单元,不然一次读取(也即是一次 I/O 操作)只可处理一转数据,逼迫会相称低。

因此,InnoDB 的数据是按「数据页」为单元来读写的,也即是说,当需要读一笔记载的时候,并不是将这个记载自己从磁盘读出来,而是以页为单元,将其合座读入内存。

数据库的 I/O 操作的最小单元是页,InnoDB 数据页的默许大小是 16KB,意味着数据库每次读写都是以 16KB 为单元的,一次最少从磁盘中读取 16K 的内容到内存中,一次最少把内存中的 16K 内容刷新到磁盘中。

数据页包括七个部分,结构如下图:

这 7 个部分的作用如下图:

在 File Header 中有两个指针,分别指朝上一个数据页和下一个数据页,邻接起来的页卓越于一个双向的链表,如下图所示:

选用链表的结构是让数据页之间不需如果物理上的连气儿的,而是逻辑上的连气儿。

数据页的主要作用是存储记载,也即是数据库的数据,是以重心说一下数据页中的 User Records 是如何组织数据的。

数据页中的记载按照「主键」律例组成单向链表,单向链表的本性即是插入、删除相称简短,然而检索逼迫不高,最差的情况下需要遍历链表上的所有这个词节点身手完成检索。

因此,数据页中有一个页目次,起到记载的索引作用,就像咱们书那样,针对书中内容的每个章节建设了一个目次,想看某个章节的时候,不错观看目次,快速找到对应的章节的页数,而数据页中的页目次即是为了能快速找到记载。

那 InnoDB 是如何给记载创建页目次的呢?页目次与记载的关系如下图:

页目次创建的历程如下:

将所有这个词的记载分袂红几个组,这些记载包括最小记载和最大记载,但不包括象征为“已删除”的记载; 每个记载组的临了一笔记载即是组内最大的那笔记载,况且临了一笔记载的头信息中会存储该组一共有些许笔记载,行为 n_owned 字段(上图中粉红色字段) 页目次用来存储每组临了一笔记载的地址偏移量,这些地址偏移量会按照先后律例存储起来,每组的地址偏移量也被称之为槽(slot),每个槽卓越于指针指向了不同组的临了一个记载。

从图不错看到,页目次即是由多个槽组成的,槽卓越于分组记载的索引。然后,因为记载是按照「主键值」从小到大排序的,是以咱们通过槽查找记载时,不错使用二分法快速定位要查询的记载在哪个槽(哪个记载分组),定位到槽后,再遍历槽内的所有这个词记载,韩国av找到对应的记载,无需从最小记载运行遍历所有这个词这个词页中的记载链表。

以上头那张图举个例子,5 个槽的编号分别为 0,1,2,3,4,我想查找主键为 11 的用户记载:

先二分得出槽中间位是 (0+4)/2=2 ,2号槽里最大的记载为 8。因为 11 > 8,是以需要从 2 号槽后继续搜索记载; 再使用二分搜索出 2 号和 4 槽的中间位是 (2+4)/2= 3,3 号槽里最大的记载为 12。因为 11 < 12,是以主键为 11 的记载在 3 号槽里; 再从 3 号槽指向的主键值为 9 记载运行向下搜索 2 次,定位到主键为 11 的记载,取出该笔记载的信息即为咱们想要查找的内容。

看到第三步的时候,可能有的同学会疑问,如果某个槽内的记载许多,然后因为记载都是单向链表串起来的,那这么在槽内查找某个记载的时代复杂度不即是 O(n) 了吗?

这点无谓追想,InnoDB 对每个分组中的记载条数都是有章程的,槽内的记载就唯有几条:

第一个分组中的记载只可有 1 笔记载; 临了一个分组中的记载条数畛域只可在 1-8 条之间; 剩下的分组中记载条数畛域只可在 4-8 条之间。 B+ 树是如何进行查询的?

上头咱们都是在说一个数据页中的记载检索,因为一个数据页中的记载是有限的,且主键值是有序的,是以通过对所有这个词记载进行分组,然后将组号(槽号)存储到页目次,使其起到索引作用,通过二分查找的方法快速检索到记载在哪个分组,来缩小检索的时代复杂度。

然而,当咱们需要存储大量的记载时,人妻无码就需要多个数据页,这时咱们就需要筹议如何建立合适的索引,身手简短定位记载场地的页。

为了惩处这个问题,InnoDB 选用了 B+ 树行为索引。磁盘的 I/O 操作次数对索引的使用逼迫至关蹙迫,因此在构造索引的时候,咱们更倾向于选用“矮胖”的 B+ 树数据结构,这么所需要进行的磁盘 I/O 次数更少,而且 B+ 树 更顺应进行重要字的畛域查询。

更详备的为什么选用 B+ 树行为索引的原因不错看我之前写的这篇:「索引为什么能升迁查询性能?」

InnoDB 里的 B+ 树中的每个节点都是一个数据页,结构透露图如下:

通过上图,咱们看出 B+ 树的本性:

唯有叶子节点(最底层的节点)才存放了数据,非叶子节点(其他表层节)仅用来存放目次项行为索引。 非叶子节点分为不同端倪,通过分层来缩小每一层的搜索量; 所有这个词节点按照索引键大小排序,组成一个双向链表,便于畛域查询;

咱们再望望 B+ 树如何已矣快速查找主键为 6 的记载,以上图为例子:

从根节点运行,通过二分法快速定位到顺应页内畛域包含查询值的页,因为查询的主键值为 6,在[1, 7)畛域之间,是以到页 30 中查找更详备的目次项; 在非叶子节点(页30)中,继续通过二分法快速定位到顺应页内畛域包含查询值的页,主键值大于 5,是以就到叶子节点(页16)查找记载; 接着,在叶子节点(页16)中,通过槽查找记载时,使用二分法快速定位要查询的记载在哪个槽(哪个记载分组),定位到槽后,再遍历槽内的所有这个词记载,找到主键为 6 的记载。

不错看到,在定位记载场地哪一个页时,亦然通过二分法快速定位到包含该记载的页。定位到该页后,又会在该页内进行二分法快速定位记载场地的分组(槽号),临了在分组内进行遍历查找。

荟萃索引和二级索引

另外,索引又不错分红荟萃索引和非荟萃索引(二级索引),它们区别就在于叶子节点存放的是什么数据:

荟萃索引的叶子节点存放的是履行数据,所有这个词完好的用户记载都存放在荟萃索引的叶子节点; 二级索引的叶子节点存放的是主键值,而不是履行数据。

因为表的数据都是存放在荟萃索引的叶子节点里,是以 InnoDB 存储引擎一定会为表创建一个荟萃索引,且由于数据在物理上只会保存一份,是以聚簇索引只可有一个。

InnoDB 在创建聚簇索引时,会证实不同的场景选拔不同的列行为索引:

如果有主键,默许会使用主键行为聚簇索引的索引键; 如果莫得主键,就选拔第一个不包含 NULL 值的惟一列行为聚簇索引的索引键; 在上头两个都莫得的情况下,InnoDB 将自动生成一个隐式自增 id 列行为聚簇索引的索引键;

一张表只可有一个聚簇索引,那为了已矣非主键字段的快速搜索,就引出了二级索引(非聚簇索引/赞助索引),它亦然应用了 B+ 树的数据结构,然而二级索引的叶子节点存放的是主键值,不是履行数据。

二级索引的 B+ 树如下图,数据部分为主键值:

因此,如果某个查询语句使用了二级索引,然而查询的数据不是主键值,这时在二级索引找到主键值后,需要去聚簇索引中取得数据行,这个历程就叫作「回表」,也即是说要查两个 B+ 树身手查到数据。不外,当查询的数据是主键值时,因为只在二级索引就能查询到,无谓再去聚簇索引查,这个历程就叫作「索引笼罩」,也即是只需要查一个 B+ 树就能找到数据。

回来

InnoDB 的数据是按「数据页」为单元来读写的,默许数据页大小为 16 KB。每个数据页之间通过双向链表的样貌组织起来,物理上不连气儿,然而逻辑上连气儿。

数据页内包含用户记载,每个记载之间用单项链表的形态组织起来,为了加速在数据页内高效查询记载,预备了一个页目次,页目次存储各个槽(分组),且主键值是有序的,于是不错通过二分查找法的形态进行检索从而升迁逼迫。

为了高效查询记载场地的数据页,InnoDB 选用 b+ 树行为索引,每个节点都是一个数据页。

如果叶子节点存储的是履行数据的即是聚簇索引,一个表只可有一个聚簇索引;如果叶子节点存储的不是履行数据,而是主键值则即是二级索引,一个表中不错有多个二级索引。

在使用二级索引进行查找数据时,如果查询的数据能在二级索引找到,那么即是「索引笼罩」操作,如果查询的数据不在二级索引里,就需要先在二级索引找到主键值,需要去聚簇索引中取得数据行,这个历程就叫作「回表」。

 

对于索引的内容还有许多,比如索引失效、索引优化等等,这些内容我下次在讲啦!

 



上一篇:大厂都在用EhCache,它到底比Redis强在那里?
下一篇:谷歌因违犯俄罗斯“数据腹地化”规章被罚金

友情链接:
  • 曰批全过程免费视频播放
  • 国产美女裸无遮挡裸体免费观网站
  • 国产精品国产一区二区三区
  • 日韩毛片
  • 欧美人与拘牲交大全视频