[串联] MySQL 存储原理 B+树

2024-03-27 10:20

本文主要是介绍[串联] MySQL 存储原理 B+树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

InnoDB 是一种兼顾高可靠性和高性能的通用存储引擎,在 MySQL 5.5 之后,InnoDB 是默认的 MySQL 存储引擎。 InnoDB 对每张表在磁盘中的存储以 xxx.ibd 后缀结尾,innoDB 引擎的每张表都会对应这样一个表空间文件,用来存储该表的表结构(frm、sdi)、数据和索引。

存储结构

InnoDB 的逻辑存储结构:表空间、段、区、页、行

https://img-blog.csdnimg.cn/95540eb1ea7349109d388ff6fc7f7cd7.png

InnoDB是以数据页为单位来读写数据的,数据页大小默认是16KB,每次从磁盘最少读取16KB的数据到内存,或者刷新内存中16KB的数据到磁盘

数据页

09b65c6b265cc577bf08a7f82ae31616

文件头记录数据页的信息,包括两个指针,一个指向上一个数据页,一个指向下一个数据页

每个数据页中存储了详细的记录数据

6c3f7e5741921f5c14903bbe06953adc

记录
  • UserRecord中存储了行记录,这些记录会通过单向链表按照主键的顺序有小到大排列
  • 单向链表的检索效率比较低,所以数据页中还有一个页目录结构帮助快速查找记录。
  • 数据页中的记录被分为若干组,当然,带有删除标识的不会参与分组;每组中的记录也是按照主键从小到大排序,每组中最后一条记录的主键值最大,它的头信息中记录了本组的记录条数(n_owned字段),页目录记录了每组最大最后一条记录的地址偏移量,叫做槽,它相当于指针指向了不同组的最后一条记录。
  • 当我们检索数据页中的记录时,由于记录都是按照主键大小排列的,可以使用槽号进行二分法定位某个槽,也就是定位到某一组,然后比较该组的最大记录的主键值,最终定位到某个槽。由于槽都是定位到每组最大的那条记录,所以如果要定位到最小的那条记录,可以通过查找上一个槽的最后一条记录,然后沿着单向链表向后检索

6675c6502cde217f24c3cff60c80212b

为了减少在某个分组中检索的时间复杂度,InnoDB规定了每个分组的大小

  1. 第一个分组只能有一条记录
  2. 最后一个分组记录条数在1-8之间
  3. 其余分组记录条数在4-8之间
B-树介绍

B-树,也称为B树,是一种平衡的多叉树。

        阶数:一个节点最多有多少个孩子节点。(一般用字母m表示)关键字:节点上的数值就是关键字度:一个节点拥有的子节点的数量。
一颗m阶的b-树:根结点至少有两个子女;每个非根节点所包含的关键字个数 j 满足:⌈m/2⌉ - 1 <= j <= m - 1.(⌈⌉表示向上取整)有k个关键字(关键字按递增次序排列)的非叶结点恰好有k+1个孩子。所有的叶子结点都位于同一层。
B+ 树原理

B+树是B-树的变体,也是一颗多路搜索树

  • 每个结点至多有m个子女;
  • 非根节点关键值个数范围:m/2 <= k <= m-1
  • 相邻叶子节点是通过指针连起来的,并且是关键字大小排序的。
## 区别:
B-树内部节点是保存数据的;而B+树内部节点是不保存数据的,只作索引作用,它的叶子节点才保存数据。
B+树相邻的叶子节点之间是通过链表指针连起来的,B-树却不是。
查找过程中,B-树在找到具体的数值以后就结束,而B+树则需要通过索引找到叶子结点中的数据才结束
B-树中任何一个关键字出现且只出现在一个结点中,而B+树可以出现多次。

a1076f005aabf2afd20d9f74ab7d5b91

  1. 插入

    流程:

    1.B+树插入都是在叶子结点进行的,就是插入前,需要先找到要插入的叶子结点。

    2.如果被插入关键字的叶子节点,当前含有的关键字数量是小于阶数m,则直接插入。

    3.如果插入关键字后,叶子节点当前含有的关键字数目等于阶数m,则插,该节点开始分裂为两个新的节点,一个节点包含⌊m/2⌋ 个关键字,另外一个关键字包含⌈m/2⌉个关键值。(⌊m/2⌋表示向下取整,⌈m/2⌉表示向上取整,如⌈3/2⌉=2)。

    4.分裂后,需要将第⌈m/2⌉的关键字上移到父结点。如果这时候父结点中包含的关键字个数小于m,则插入操作完成。

    5.分裂后,需要将⌈m/2⌉的关键字上移到父结点。如果父结点中包含的关键字个数等于m,则继续分裂父结点。

    参考:https://juejin.cn/post/6929833495082565646?searchId=20240301221957FB5B4942920DC0A4744E

  2. 查找

    单值查询:查找32

    第一次磁盘 I/O,查找磁盘块1,即根节点(36,43),因为32小于36,因此访问根节点的左边第一个孩子节点

    第二次磁盘 I/O, 查找磁盘块2,即根节点的第一个孩子节点,获得区间(28,32),遍历即可得32.

    img

    范围查询: [32,40]

    第一步先访问根节点,发现区间的左端点32小于36,则访问根节点的第一个左子树(28,32);

    第二步访问节点(28,32),找到32,于是开始遍历链表,把[32,40]区间值找出来,这也是B+树比B-树高效的地方。

  3. 删除
  • 找到包含关键值的结点,如果关键字个数大于m/2,直接删除即可;
  • 找到包含关键值的结点,如果关键字个数大于m/2,并且关键值是当前节点的最大(小)值,并且该关键值存在父子节点中,那么删除该关键字,同时需要相应调整父节点的值。
  • 找到包含关键值的结点,如果删除该关键字后,关键字个数小于⌈m/2⌉,并且其兄弟结点有多余的关键字,则从其兄弟结点借用关键字
  • 找到包含关键值的结点,如果删除该关键字后,关键字个数小于⌈m/2⌉,并且其兄弟结点没有多余的关键字,则与兄弟结点合并。
常见问题
  1. InnoDB一棵B+树可以存放多少行数据?

    约2千万行

    在计算机中,磁盘存储数据最小单元是扇区,一个扇区的大小是512字节。
    文件系统中,最小单位是块,一个块大小就是4k;
    InnoDB存储引擎最小储存单元是页,一页大小就是16k。
    
    • 如果一行记录的数据大小为1k,那么单个叶子节点可以存的记录数 =16k/1k =16.
    • 假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,非叶节点的一条记录为8+6=14字节,可存放16k/14B= 1170条
    • 因此,一棵高度为2的B+树,能存放1170 * 16=18720条这样的数据记录。同理一棵高度为3的B+树,能存放1170 *1170 *16 =21902400,也就是说,可以存放两千万左右的记录。B+树高度一般为1-3层,已经满足千万级别的数据存储。

    img

  2. 为什么索引结构默认使用B+树,而不是hash,二叉树,红黑树,B-树?
    • Hash哈希,只适合等值查询,不适合范围查询。

    • 一般二叉树,可能会特殊化为一个链表,相当于全表扫描。

    • 红黑树,是一种特化的平衡二叉树,MySQL 数据量很大的时候,索引的体积也会很大,内存放不下的而从磁盘读取,树的层次太高的话,读取磁盘的次数就多了。

    • B-Tree,叶子节点和非叶子节点都保存数据,相同的数据量,B+树更爱矮壮,也是就说,相同的数据量,B+树数据结构,查询磁盘的次数会更少。

  3. B-树和B+树的区别
    • B-树内部节点是保存数据的;而B+树内部节点是不保存数据的,只作索引作用,它的叶子节点才保存数据。
    • B+树相邻的叶子节点之间是通过链表指针连起来的,B-树却不是。
    • 查找过程中,B-树在找到具体的数值以后就结束,而B+树则需要通过索引找到叶子结点中的数据才结束
    • B-树中任何一个关键字出现且只出现在一个结点中,而B+树同一个键值可在不同层级的节点中重复出现。
  4. B+树和红黑树的区别
    • B+树的所有值都存在于叶子节点,并且叶子节点之间通过指针连接,形成一个有序链表。这种结构非常适合范围查询,红黑树虽然在单个元素查找上有优势,但需要进行额外的遍历才能完成范围查询。
    • 由于B+树具有顺序访问的特性,数据库系统可以利用预读优化来提高连续磁盘块的读取性能。而红黑树的结构不容易进行批量的顺序读取操作,因此无法充分利用预读特性。
    • B+树通过将键和数据分离使得节点可以存放更多的键。这样就可以减少树的高度,红黑树作为二叉树在存储大量数据时会占据更多空间,因为每个节点只有两个子节点的指针。
  5. 为什么索引使用B+树不使用跳表?

    磁盘I/O效率:B+树特别适合于磁盘存储的优化。它们能够最小化磁盘I/O操作,因为一个节点通常对应一个磁盘块的大小,这样可以减少读取数据时所需的磁盘访问次数。跳表在内存中运行效率较高,但当涉及到磁盘操作时,其性能可能会下降,因为跳表的节点间隔是不规则的,不一定能有效利用磁盘块的空间。

    删除操作:在B+树中,插入和删除操作可以更容易地保持树的平衡,而且不需要重新组织整个数据结构。虽然跳表支持比较简单的插入和删除操作,但在大量的更新操作后可能需要额外的工作来重新平衡。

    存储利用率:B+树的节点通常设计为页大小,以便与磁盘或文件系统页面对齐,从而实现高效的空间利用。而跳表可能会因为其节点大小不一致而在某些情况下导致存储空间利用率不高。

这篇关于[串联] MySQL 存储原理 B+树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/851777

相关文章

mysql索引四(组合索引)

单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引;组合索引,即一个索引包含多个列。 因为有事,下面内容全部转自:https://www.cnblogs.com/farmer-cabbage/p/5793589.html 为了形象地对比单列索引和组合索引,为表添加多个字段:    CREATE TABLE mytable( ID INT NOT NULL, use

mysql索引三(全文索引)

前面分别介绍了mysql索引一(普通索引)、mysql索引二(唯一索引)。 本文学习mysql全文索引。 全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。 在MySql中,创建全文索引相对比较简单。例如:我们有一个文章表(article),其中有主键ID(

mysql索引二(唯一索引)

前文中介绍了MySQL中普通索引用法,和没有索引的区别。mysql索引一(普通索引) 下面学习一下唯一索引。 创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复。唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该使用关键字UNIQUE,把它定义为一个唯一索引。 添加数据库唯一索引的几种

mysql索引一(普通索引)

mysql的索引分为两大类,聚簇索引、非聚簇索引。聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引则不同。聚簇索引能够提高多行检索的速度、非聚簇索引则对单行检索的速度很快。         在这两大类的索引类型下,还可以降索引分为4个小类型:         1,普通索引:最基本的索引,没有任何限制,是我们经常使用到的索引。         2,唯一索引:与普通索引

【服务器运维】MySQL数据存储至数据盘

查看磁盘及分区 [root@MySQL tmp]# fdisk -lDisk /dev/sda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical)

SQL Server中,查询数据库中有多少个表,以及数据库其余类型数据统计查询

sqlserver查询数据库中有多少个表 sql server 数表:select count(1) from sysobjects where xtype='U'数视图:select count(1) from sysobjects where xtype='V'数存储过程select count(1) from sysobjects where xtype='P' SE

SQL Server中,always on服务器的相关操作

在SQL Server中,建立了always on服务,可用于数据库的同步备份,当数据库出现问题后,always on服务会自动切换主从服务器。 例如192.168.1.10为主服务器,12为从服务器,当主服务器出现问题后,always on自动将主服务器切换为12,保证数据库正常访问。 对于always on服务器有如下操作: 1、切换主从服务器:假如需要手动切换主从服务器时(如果两个服务

SQL Server中,isnull()函数以及null的用法

SQL Serve中的isnull()函数:          isnull(value1,value2)         1、value1与value2的数据类型必须一致。         2、如果value1的值不为null,结果返回value1。         3、如果value1为null,结果返回vaule2的值。vaule2是你设定的值。        如

SQL Server中,添加数据库到AlwaysOn高可用性组条件

1、将数据添加到AlwaysOn高可用性组,需要满足以下条件: 2、更多具体AlwaysOn设置,参考:https://msdn.microsoft.com/zh-cn/library/windows/apps/ff878487(v=sql.120).aspx 注:上述资源来自MSDN。

SQL Server中,用Restore DataBase把数据库还原到指定的路径

restore database 数据库名 from disk='备份文件路径' with move '数据库文件名' to '数据库文件放置路径', move '日志文件名' to '日志文件存放置路径' Go 如: restore database EaseWe from disk='H:\EaseWe.bak' with move 'Ease