Innodb引擎中B+树一般有几层?能容纳多少数据量?

参考:
面试题:InnoDB中B+树有几层?_Running-Waiting的博客-优快云博客_b+树有几层

mysql单表最多两千万条数据?

先说结论一般B+树高大约为1~3层(通过主键索引查询,通常磁盘io数为1~3次),可容纳记录数约2000w条

 
在 MySQL 中我们的 InnoDB 页的大小默认是 16k,当然也可以通过参数设置。
在查找数据时一次页的查找代表一次 IO,所以通过主键索引查询通常只需要 1~3 次 IO 操作即可查找到数据。

1、MySQL的InnoDB存储引擎的最小存储单元是页(大小默认是16k,可通过参数设置)。页可用于存放B+树叶节点数据,也可用于存放B+树非叶节点的 “键 + 指针”
2、索引组织表通过非叶节点的 “二分查找” 法以及指针确定数据在下一层的哪个页中,进而再去叶节点的数据页中查找到所需数据。

一个非叶节点可容纳约1170个指针,这里假设一行记录数据大小为 1k,那么底层叶节点一页16k就能存16条记录。叶节点数 * 一个叶节点能存放的记录数 = 1170 * 16 = 18720条 记录数。具体推导过程如图:

同理可得:高度为3的B+树能存的记录数为:1170*1170*16=21902400,2190w条记录,约2000w条记录。

为什么MySQL用B+树而不用B树呢?

因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO 操作变多,查询性能变低。

总结:

  1. B+树叶子和非叶子节点的数据页都是16k,且数据结构一致,区别在于叶子节点放的是真实的行数据,而非叶子节点放的是主键和下一个页的地址。
  2. B+树一般有两到三层,由于其高扇出,三层就能支持2kw以上的数据,且一次查询最多1~3次磁盘IO,性能也还行。
  3. 存储同样量级的数据,B树比B+树层级更高,因此磁盘IO也更多,所以B+树更适合成为MySQL索引。
  4. 索引结构不会影响单表最大行数,2kw也只是推荐值,超过了这个值可能会导致B+树层级更高,影响查询性能。
  5. 单表最大值还受主键大小和磁盘大小限制。
<think>好的,我需要回答用户的问题:为什么MySQL索引使用B+而不是B。根据提供的引用,特别是引用[1]、[2]、[3],我需要整理出主要原因。 首先,引用[1]提到B+解决了B遍历效率低的问题,因为B+的所有叶子节点形成有序链表,便于范围查询。而B的范围查询需要复杂的遍历,效率低。这点很重要,因为数据库经常有范围查询的需求。 其次,引用[2]指出B+在磁盘IO性能上的优势。B+的内部节点不存储数据,只存键,所以每个节点能容纳更多键,的高度更低,减少磁盘访问次数。而B的节点存储数据,导致节点容量小,更高,IO次数多。这对数据库来说很关键,因为磁盘IO是性能瓶颈。 引用[3]提到B+的稳定性更好,而红黑或二叉可能在频繁插入删除时退化成链表,影响性能。不过这里主要对比B,所以可能需要补充B+的叶子节点链表带来的顺序访问优势。 另外,引用[4]显示索引类型是B+,进一步支持结论。 总结几点:1. 范围查询高效;2. 磁盘IO优化(节点结构);3. 顺序访问性能;4. 更稳定的结构。需要将这些点用中文清晰组织,引用对应的引用来源,并确保符合用户要求的格式,如使用$...$和$$...$$,生成相关问题。</think>### MySQL索引使用B+而非B的核心原因 --- #### 一、**范围查询性能优势** 1. **B+的叶子节点链表结构** B+的所有叶子节点通过指针**顺序连接成链表**,而B的叶子节点是独立的。 例如,执行`SELECT * FROM table WHERE id BETWEEN 100 AND 500`时: - **B+**:直接遍历叶子节点链表即可获取所有符合条件的数据,时间复杂度为$O(n)$($n$为结果数量)[^1][^3]。 - **B**:需要从根节点多次向下查找,可能涉及不同层级的节点遍历,效率显著降低[^1]。 --- #### 二、**磁盘I/O效率优化** 1. **节点存储密度的差异** - **B+内部节点不存储数据**:仅存储键和子节点指针,单个节点可容纳更多键值,的高度更低。假设每个节点大小为16KB: $$ \text{B+单节点键数} ≈ \frac{16\text{KB}}{\text{键大小} + \text{指针大小}} $$ 例如,键为`BIGINT`(8字节)+ 指针(6字节),单节点可存约$16\text{KB}/14\text{B} ≈ 1170$个键,高为3时支持约$1170^3=1.6$亿条数据[^1][^2]。 - **B节点存储数据**:每个节点需存储键和数据指针,导致单节点键数减少,高增加,磁盘I/O次数上升[^1][^3]。 2. **磁盘预读特性适配** B+的连续叶子节点布局更符合磁盘顺序读取特性(每次读取一页数据),而B的分散数据分布可能引发随机I/O[^2]。 --- #### 三、**查询稳定性与全表扫描效率** 1. **稳定的查询路径长度** B+中**所有查询均需到达叶子节点**,路径长度固定(高$h$),时间复杂度稳定为$O(h)$。而B可能在内部节点提前命中数据,导致查询路径长度波动。 2. **全表扫描无需回溯结构** 通过遍历叶子节点链表即可完成全表扫描(时间复杂度$O(n)$),而B需要递归遍历整棵[^1]。 --- #### 四、**B对比总结** | **特性** | **B** | **B+** | |--------------------|----------------------------------|----------------------------------| | 数据存储位置 | 所有节点均可存数据 | 仅叶子节点存数据 | | 范围查询效率 | 低(需跨层遍历) | 高(顺序链表遍历) | | 高度 | 较高(节点键数少) | 较低(节点键数多) | | 全表扫描 | 需要遍历整棵 | 仅需遍历叶子链表 | | 适用场景 | 少量随机查询 | 高并发范围查询、OLAP | --- #### 五、**实验验证** ```sql -- 创建测试表 CREATE TABLE test ( id INT PRIMARY KEY, data VARCHAR(100) ) ENGINE=InnoDB; -- 查看索引类型(显示为B+) SHOW INDEX FROM test; ``` 输出结果中的`Index_type: BTREE`实际指代B+MySQL内部命名习惯)[^4]。 --- ### 相关问题 1. **B+如何通过叶子节点链表优化范围查询?** 2. **为什么B+的节点存储密度比B更高?** 3. **MySQL的B+索引如何适配机械硬盘和SSD的不同特性?**
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值