一般来说主键索引的树深度有几层?为什么是这个层数?

主键索引B+树深度解析

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.6k人参与

这是一个非常棒的问题,它触及了数据库索引设计的核心。简单答案是:

对于一个存储了数百万甚至数十亿条记录的大型表,其主键索引的B+树深度通常也只有3到4层。极少有情况会达到5层或以上。

这个看似神奇的层数背后,是B+树数据结构极其高效的高扇出(High Fan-out) 特性。


为什么层数这么少?—— 关键在于“扇出”

扇出(Fan-out) 指的是一个索引节点中可以存储的子节点指针(或键值)的数量。B+树之所以强大,就是因为它的每个节点都能存储非常多的键值和指针,这使得树可以变得“又宽又胖”,而不是“又瘦又高”。

树的深度(层数)直接决定了查找一条记录需要多少次磁盘I/O操作。因为每次向下遍历一层,通常就需要一次磁盘读取(除非节点已被缓存)。所以,保持较浅的深度是高性能的关键。

层数计算:一个具体的例子

让我们用一些合理的假设来估算一下:

  1. 假设1:页大小(Page Size)
    在InnoDB中,默认的页大小是 16KB。这是B+树每个节点的大小。

  2. 假设2:主键字段大小
    假设我们使用一个 BIGINT(8字节) 作为主键。

  3. 假设3:指针大小
    在InnoDB中,一个指向子节点(或数据行)的指针大约需要 6字节

  4. 计算非叶子节点的扇出
    一个非叶子节点存储的内容是:(主键值 + 子节点指针)
    每个这样的组合大约占用:8字节 + 6字节 = 14字节
    一个16KB的页大约能存储:16 * 1024 / 14 ≈ 1170 个这样的组合。
    也就是说,一个非叶子节点可以指向大约1170个子节点

  5. 计算叶子节点的容量
    叶子节点存储的是完整的行数据(在MySQL的聚集索引中)或主键值+指针(在PostgreSQL的堆表中)。这里我们以MySQL为例,假设一行数据平均大小为 1KB(这是一个很常见的估算值)。
    那么一个16KB的页大约能存储:16 / 1 ≈ 16 行数据。

现在,我们来计算这棵B+树能存储多少数据:

  • 深度 = 1:根节点也是叶子节点。

    • 最多存储 16 行记录。
  • 深度 = 2:1个根节点(非叶子) + 多个叶子节点。

    • 根节点可以指向 1170 个叶子节点。
    • 总记录数 = 1170 * 16 ≈ 18,720 行。
  • 深度 = 3

    • 根节点可以指向 1170 个非叶子节点。
    • 每个非叶子节点又可以指向 1170 个叶子节点。
    • 总记录数 = 1170 * 1170 * 16 ≈ 21,902,400 行(约 2200万)。
  • 深度 = 4

    • 总记录数 = 1170 * 1170 * 1170 * 16 ≈ 25,629,807,200 行(约 256亿)。

从这个计算可以看出:

  • 仅仅3层的B+树就能轻松支持两千万级别的数据量。
  • 达到4层,就能支持两百五十亿级别的恐怖数据量,这已经远超绝大多数应用整个生命周期的数据总量。

影响树深度的关键因素

从上面的计算公式可以看出,深度主要由以下几个因素决定:

  1. 页大小(Page Size):这是最重要的因素。页越大,一个节点能存储的键值和指针就越多(扇出越高),树就越浅。MySQL可以配置页大小(如8KB, 16KB, 32KB, 64KB),但16KB是默认且最平衡的选择。
  2. 主键的大小:主键字段越小,每个非叶子节点能存储的键值就越多,扇出就越高。这就是为什么通常推荐使用 短小的自增整数(如BIGINT) 作为主键,而不是很长的字符串(如UUID)。
    • 反面例子:如果你用 CHAR(100) 做主键,假设需要100字节。那么一个非叶子节点只能存储 16*1024 / (100+6) ≈ 154 个键值指针对。扇出从1170暴跌到154,要存储同样多的数据,树的深度就必须增加。
  3. 行数据的大小(仅对MySQL聚集索引影响显著):行数据越小,每个叶子页能存放的行数就越多,整棵树能存储的总行数就越大。因此,避免设计过宽的表、将TEXT/BLOB等大字段分表存储,也有助于优化索引深度。

总结

  • 核心原因:B+树拥有极高的扇出,使得树又宽又胖,而非又瘦又高。
  • 典型层数:对于亿级以下的表,3层是常态。对于十亿到百亿级的表,4层也足够。5层以上的B+树极其罕见,通常意味着表设计可能存在问题(例如使用了非常低效的主键)。
  • 设计启示:为了保持索引树浅而高效,应该使用短小、自增的整数作为主键。这不仅能减少非叶子节点的扇出,还能保证顺序写入,减少页分裂和碎片,对性能提升至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值