一颗B+树可以存储多少数据?

一、前言

这个问题,非常经典,考察的点很多:

比如:

        1、操作系统存储的单元,毕竟mysql也是运行在操作系统之上的应用。

        2、B+树是针对Mysql的InnoDB存储引擎,所以要理解InnoDb的最小存储单元,页,区,段的概念,尤其是页的格式,里面有哪些构成。

        2、明确这颗B+树一定是由主键索引构建的B+树,所以最终的数据是存储在叶子结点,非叶子节点,只存储主键索引,所以主键索引的大小决定了最终能存放多少数据。

答案:

主键为bigint(约2000w):

2层B+树的话:可以存放1170个*16条=18720条(行)数据。
3层B+树的话:可以存放1170个*1170个*16条=21902400条(行)数据。

主键为int(约4000w):

2层B+树的话:可以存放1600个*16条=25600条(行)数据。
3层B+树的话:可以存放1600个*1600个*16条=40960000条(行)数据。

在使用主流磁盘存储的条件一下,查询一条数据的时间在50ms内

二、磁盘存储和InnoDB的存储

我们都知道计算机在存储数据的时候,有最小存储单元,这就好比我们今天进行现金的流通最小单位是一毛。在计算机中磁盘存储数据最小单元是扇区,一个扇区的大小是512字节,而文件系统(例如XFS/EXT4)他的最小单元是块,一个块的大小是4k,

下面几张图可以帮你理解最小存储单元:

文件系统中一个文件大小只有1个字节,但不得不占磁盘上4KB的空间。

而对于我们的InnoDB存储引擎也有自己的最小储存单元——页(Page),一个页的大小是16K,如下图所示:

并且innodb所有的数据文件也就是我们之前提到的后缀为.ibd的文件,它们的大小都是16k的整数倍。

由于数据库的索引是保存到磁盘上的,因此当我们通过索引查找某行数据的时候,就需要先从磁盘读取索引到内存,再通过索引从磁盘中找到某行数据,然后读入到内存,也就是说查询过程中会发生多次磁盘 I/O,而磁盘 I/O 次数越多,所消耗的时间也就越大。

所以,我们希望索引的数据结构能在尽可能少的磁盘的 I/O 操作中完成查询工作,因为磁盘 I/O 操作越少,所消耗的时间也就越小。

另外,MySQL 是支持范围查找的,所以索引的数据结构不仅要能高效地查询某一个记录,而且也要能高效地执行范围查找。

所以,要设计一个适合 MySQL 索引的数据结构,至少满足以下要求:

  • 能在尽可能少的磁盘的 I/O 操作中完成查询工作;
  • 要能高效地查询某一个记录,也要能高效地执行范围查找;

记录是按照行来存储的,但是数据库的读取并不以「行」为单位,否则一次读取(也就是一次 I/O 操作)只能处理一行数据,效率会非常低。

因此,InnoDB 的数据是按「数据页」为单位来读写的,也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。

三、Innodb数据页格式

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

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

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

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

采用链表的结构是让数据页之间不需要是物理上的连续的,而是逻辑上的连续。

数据页的主要作用是存储记录,也就是数据库的数据,所以重点说一下数据页中的 User Records 是怎么组织数据的。

数据页中的记录按照「主键」顺序组成单向链表,单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索。

因此,数据页中有一个页目录,起到记录的索引作用,就像我们书那样,针对书中内容的每个章节设立了一个目录,想看某个章节的时候,可以查看目录,快速找到对应的章节的页数,而数据页中的页目录就是为了能快速找到记录。

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

页目录创建的过程如下:

  1. 将所有的记录划分成几个组,这些记录包括最小记录和最大记录,但不包括标记为“已删除”的记录;
  2. 每个记录组的最后一条记录就是组内最大的那条记录,并且最后一条记录的头信息中会存储该组一共有多少条记录,作为 n_owned 字段(上图中粉红色字段)
  3. 页目录用来存储每组最后一条记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量也被称之为槽(slot),每个槽相当于指针指向了不同组的最后一个记录

从图可以看到,页目录就是由多个槽组成的,槽相当于分组记录的索引。然后,因为记录是按照「主键值」从小到大排序的,所以我们通过槽查找记录时,可以使用二分法快速定位要查询的记录在哪个槽(哪个记录分组),定位到槽后,再遍历槽内的所有记录,找到对应的记录,无需从最小记录开始遍历整个页中的记录链表。

以上面那张图举个例子,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 对应最大主键是 12 的记录,那如何找到最小记录 9。解决办法是:通过槽 3 找到 槽 2 对应的记录,也就是主键为 8 的记录。主键为 8 的记录的下一条记录就是槽 3 当中主键最小的 9 记录,然后开始向下搜索 2 次,定位到主键为 11 的记录,取出该条记录的信息即为我们想要查找的内容。

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

这点不用担心,InnoDB 对每个分组中的记录条数都是有规定的,槽内的记录就只有几条:

  • 第一个分组中的记录只能有 1 条记录;
  • 最后一个分组中的记录条数范围只能在 1-8 条之间;
  • 剩下的分组中记录条数范围只能在 4-8 条之间。

四、B+ 树是如何进行查询的?

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

但是,当我们需要存储大量的记录时,就需要多个数据页,这时我们就需要考虑如何建立合适的索引,才能方便定位记录所在的页。

为了解决这个问题,InnoDB 采用了 B+ 树作为索引。磁盘的 I/O 操作次数对索引的使用效率至关重要,因此在构造索引的时候,我们更倾向于采用“矮胖”的 B+ 树数据结构,这样所需要进行的磁盘 I/O 次数更少,而且 B+ 树 更适合进行关键字的范围查询。

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

通过上图,我们看出 B+ 树的特点:

  • 只有叶子节点(最底层的节点)才存放了数据,非叶子节点(其他上层节)仅用来存放目录项作为索引。
  • 非叶子节点分为不同层次,通过分层来降低每一层的搜索量;
  • 所有节点按照索引键大小排序,构成一个双向链表,便于范围查询;

我们再看看 B+ 树如何实现快速查找主键为 6 的记录,以上图为例子:

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

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

总结

InnoDB 的数据是按「数据页」为单位来读写的,默认数据页大小为 16 KB。每个数据页之间通过双向链表的形式组织起来,物理上不连续,但是逻辑上连续。

数据页内包含用户记录,每个记录之间用单向链表的方式组织起来,为了加快在数据页内高效查询记录,设计了一个页目录,页目录存储各个槽(分组),且主键值是有序的,于是可以通过二分查找法的方式进行检索从而提高效率。

为了高效查询记录所在的数据页,InnoDB 采用 b+ 树作为索引,每个节点都是一个数据页。

如果叶子节点存储的是实际数据的就是聚簇索引,一个表只能有一个聚簇索引;如果叶子节点存储的不是实际数据,而是主键值则就是二级索引,一个表中可以有多个二级索引。

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

同理三层高的B+树

叶子节点的一条记录按照1k算

1170*1170*16 约等于 两千万

根结点常驻内存,根据磁盘每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计。

那么访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms左右。

那么在有索引的条件下,查询一个数据大约需要两次IO,在两千万数据的量级下,时间可以控制在20ms左右。

参考文献

https://www.cnblogs.com/leefreeman/p/8315844.html

mysql 最大建议行数2000w,靠谱吗? - 京东云开发者的个人空间 - OSCHINA - 中文开源技术交流社区

 MySQL InnoDB引擎——三层B+树可以存储多少数据量_3层b+树可以存多少数据-CSDN博客

面试官问我为啥B+树一般都不超过3层?3层B+树能存多少数据?redo log与binlog的两阶段提交?_b+树为什么三层-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Arduino】实验使用ESP32单片机根据光线变化控制LED小灯开关(图文)

今天小飞鱼继续来实验ESP32的开发&#xff0c;这里使用关敏电阻来配合ESP32做一个我们平常接触比较多的根据光线变化开关灯的实验。当白天时有太阳光&#xff0c;则把小灯关闭&#xff1b;当光线不好或者黑天时&#xff0c;自动打开小灯。 int value;void setup() {pinMode(34…

java基于ssm+jsp 美食推荐管理系统

1前台首页功能模块 美食推荐管理系统&#xff0c;在系统首页可以查看首页、热门美食、美食教程、美食店铺、美食社区、美食资讯、我的、跳转到后台等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户注册&#xff0c;在注册页面可以填写用户名、密码、姓名、联系电话等…

什么是 vCPU?有什么作用

vCPU 是物理 CPU 的虚拟化版本&#xff0c;是云计算的基本组成部分。这些虚拟化计算单元的一大优势是其良好的可扩展性&#xff0c;这也是它们在云托管中发挥重要作用的原因。 vCPU 有什么作用? vCPU(虚拟中央处理器)是物理CPU的虚拟化变体。换句话说&#xff0c;vCPU 是虚拟机…

ctfshow 2023 愚人杯 web

easy_signin 观察url&#xff0c;发现base64 &#xff0c;进行解码&#xff0c;原来可以访问文件路径&#xff0c;那我们访问一下index.php ?imgaW5kZXgucGhw查看源代码发现还是base64 解码得到flag 被遗忘的反序列化 <?php# 当前目录中有一个txt文件哦 error_reporti…

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验

目录 一、实验原理二、实验步骤1. 图像读取与预处理2. 边缘检测3. 轮廓检测4. 标记轮廓序号 三、实验结果 Hi&#xff0c;大家好&#xff0c;我是半亩花海。 本实验旨在利用 Python 和 OpenCV 库&#xff0c;通过图像处理和边缘检测算法实现黄豆图像的自动识别和计数&#xff0…

MarkDown基础

一、MarkDown标题 1.使用和-表示一级标题 2.使用#、##、###、####、######、######表示一级至六级标题 一级标题 二级标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 二、MarkDown标题 1.Markdown 段落没有特殊的格式&#xff0c;直接编写文字就好&#xff0c;…

适耳贴合的气传导耳机,带来智能生活体验,塞那Z50耳夹耳机上手

现在大家几乎每天都会用到各种AI产品&#xff0c;蓝牙耳机也是我们必不可少的装备&#xff0c;最近我发现一款很好用的分体式气传导蓝牙耳机&#xff0c;它还带有一个具备AI功能的APP端&#xff0c;大大方便了我们日常的使用。这款sanag塞那Z50耳夹耳机我用过一段时间以后&…

共93本!全网最全Frontiers旗下期刊2022、2023版影响因子和分区对比完整版目录!

本周投稿推荐 SSCI • 1区&#xff0c;4.0-5.0&#xff08;无需返修&#xff0c;提交可录&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; CNKI • 7天录用-检索&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#xff0c;0.1-0.5&…

postman测试接口使用

背景&#xff1a; 隔了一段时间没有用postman&#xff0c;有些忘记了&#xff0c;谨以此文来记录postman的使用&#xff0c;如有忘记就可以快速回忆 使用&#xff1a; 点击这个号&#xff0c;是创建接口页面 这里的复选框可供我们选择接口的rest方式 请求路径&#xff1a; …

qt 简单实验 一个可以向左侧拖拽缩放的矩形

1.概要 向左拖拽矩形&#xff0c;和向右拖拽不同&#xff0c;向右拖拽是增加宽度&#xff0c;向左拖拽是增加宽度的同时还要向左移动x的坐标。 2.代码 2.1 resizablerectangleleft.h #ifndef RESIZABLERECTANGLELEFT_H #define RESIZABLERECTANGLELEFT_H #include <QWid…

java基于ssm+jsp 母婴用品网站

1管理员功能模块 管理员登录&#xff0c;管理员通过输入用户名、密码等信息进行系统登录&#xff0c;如图1所示。 图1管理员登录界面图 管理员登录进入母婴用品网站可以查看主页、个人中心、用户管理、商品分类管理、商品信息管理、留言板管理、成长交流、系统管理、订单管理、…

Desoutter智能拧紧中枢Connect过压维修

马头智能拧紧中枢过压维修是马头拧紧设备维护中的重要环节。当出现马头拧紧设备中枢过压现象时&#xff0c;会导致设备性能下降&#xff0c;甚至损坏设备&#xff0c;因此及时对过压中枢进行维修是保障设备正常运转的关键。 Desoutter电动螺丝刀控制器过压的原因可能有很多&am…

AUCell和AddModuleScore函数进行基因集评分

AUCell 和AddModuleScore 分析是两种主流的用于单细胞RNA测序数据的基因集活性分析的方法。这些基因集可以来自文献、数据库或者根据具体研究问题进行自行定义。 AUCell分析原理&#xff1a; 1、AUCell分析可以将细胞中的所有基因按表达量进行排序&#xff0c;生成一个基因排…

Boosting Weakly-Supervised Temporal Action Localization with Text Information

标题&#xff1a;利用文本信息增强弱监督时间动作定位 源文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2023/papers/Li_Boosting_Weakly-Supervised_Temporal_Action_Localization_With_Text_Information_CVPR_2023_paper.pdfhttps://openaccess.thecvf.com/…

计算机系统基础实训五—CacheLab实验

实验目的与要求 1、让学生更好地应用程序性能的优化方法&#xff1b; 2、让学生更好地理解存储器层次结构在程序运行过程中所起的重要作用&#xff1b; 3、让学生更好地理解高速缓存对程序性能的影响&#xff1b; 实验原理与内容 本实验将帮助您了解缓存对C程序性能的影响…

Node.js 渲染三维模型并导出为图片

Node.js 渲染三维模型并导出为图片 1. 前言 本文将介绍如何在 Node.js 中使用 Three.js 进行 3D 模型渲染。通过结合 gl 和 canvas 这两个主要依赖库&#xff0c;我们能够在服务器端实现高效的 3D 渲染。这个方法解决了在服务器端生成和处理 3D 图形的需求&#xff0c;使得可…

智能汽车 UI 风格独具魅力

智能汽车 UI 风格独具魅力

工业web4.0UI风格令人惊艳

工业web4.0UI风格令人惊艳

1095 解码PAT准考证(测试点3)

solution 测试点3超时&#xff1a;命令为3时&#xff0c;用unordered_map而非map&#xff0c;否则会超时 #include<iostream> #include<string> #include<algorithm> #include<unordered_map> using namespace std; const int maxn 1e4 10; struct…

基于uniapp的h5接入企业微信客服在线聊天

首先说下企业微信接入场景,支持的接入场景有以下几种,基本上涵盖了微信生态大部分场景: 接入步骤 1.创建企业微信号 按照官方操作步骤注册,需要注意的是未认证仅支持接入100人,已认证支持接入2000人. 2.创建客服账号 每个客服账号支持配置人工或是机器人或是人工机器人回复…