InnoDB中高度为3的B+树最多可以存多少数据?

参考:

🔥我说MySQL每张表最好不超过2000万数据,面试官让我回去等通知? - 掘金

考虑到磁盘IO是非常高昂的操作,计算机操作系统做了预读的优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。

每一次IO读取的数据我们称之为一页(page),具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO。MySQL每个节点大小默认为16KB,也就是每个节点最多存16KB的数据,可以修改,最大64KB,最小4KB。

如果某一行数据太大了超过16KB怎么办?

如果行超过最大行长度, 则将可变长度列用外部页存储,直到该行符合最大行长度限制。 就是说把varchar、text这种长度可变的存到外部页中,来减小这一行的数据长度。只在该列上保留一个 20 字节的指针指向溢出页。

索引页就是存索引的节点,也就是非叶子节点。

每一条索引记录当中都包含了当前索引的值一个 6字节 的指针信息一个 5 字节的行标头,用来指向下一层数据页的指针。

假设我们的主键id为 bigint 型,也就是8个字节,那索引页中每行数据占用的空间就等于 8+6+5=198+6+5=19 字节。每页可以存 15232÷19≈80115232÷19≈801 条索引数据。

那算上页目录的话,按每个槽平均6条数据计算的话,至少有 801÷6≈134801÷6≈134 个槽,需要占用 268 字节的空间。

把存数据的空间分一点给槽的话,我算出来大约可以存787 条索引数据。

如果是主键是 int 型的话,那可以存更多,大约有 993条索引数据。

前两层非叶子节点计算

在 B+ 树当中,当一个节点索引记录为 N 条时,它就会有 N 个子节点。由于我们 3 层B+树的前两层都是索引记录,第一层根节点有 N 条索引记录,那第二层就会有 N 个节点,每个节点数据类型与根节点一致,仍然可以再存 N 条记录,第三层的节点个数就会等于 N * N。

则有:

  • 主键为 bigint 的表可以存放 787 * 787=619369 个叶子节点(约等于62w)
  • 主键为 int 的表可以存放 993 * 993=986049 个叶子节点(约等于99w)

分析一下这张表的行记录:

  1. 行记录头信息:肯定得有,占用5字节。
  2. 可变长度字段列表:表中 title占用1字节,description占用2字节,共3字节。
  3. null值列表:表中仅school_codecover_imagerelease_time3个字段可为null,故仅占用1字节。
  4. 事务ID和指针字段:两个都得有,占用13字节。
  5. 字段内容信息:
    1. id、author_id、school_code 均为bigint型,各占用8字节,共24字节。
    2. create_time、release_time、modified_time 均为datetime类型,各占8字节,共24字节。
    3. status、is_delete 为tinyint类型,各占用1字节,共2字节。
    4. cover_image 为char(32),字符编码为表默认值utf8,由于该字段实际存的内容仅为英文字母(存url的),结合前面讲的字符编码不同情况下的存储 ,故仅占用32字节。
    5. title、description 分别为varchar(50)、varchar(250),这两个应该都不会产生溢出页(不太确定),字符编码均为utf8mb4,实际生产中70%以上都是存的中文(3字节),25%为英文(1字节),还有5%为4字节的表情😁,则存满的情况下将占用 (50+250)×(0.7×3+0.25×1+0.05×4)=765(50+250)×(0.7×3+0.25×1+0.05×4)=765 字节。

统计上面的所有分析,共占用 869 字节,则每个叶子节点可以存放 15232÷869≈1715232÷869≈17 条,算上页目录,仍然能放 17 条。

则三层B+树可以存放的最大数据量就是 17×619369=10,529,273,约一千万条数据,再次没想到吧👴。

以下是粗略估算:

InnoDB存储引擎中页的大小为16KB,一般表的主键类型为INT(占用4个字节)或BIGINT(占用8个字节),指针类型也一般为4或8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值(因为是估值,为方便计算,这里的K取值为〖10〗^3)。

也就是说一个深度为3的B+Tree索引可以维护10^3 * 10^3 * 10^3 = 10亿 条记录。(这种计算方式存在误差,而且没有计算叶子节点,如果计算叶子节点其实是深度为4了)

相关推荐
Yan.love2 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
冠位观测者12 分钟前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡3 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做4 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa4 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL5 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者11 小时前
5820 丰富的周日生活
数据结构·算法