B-Tree和B+Tree

文章讨论了内存访问速度远超硬盘,因此在数据存储设计中需要减少IO次数。B-Tree和B+Tree是两种优化IO的操作数据结构,B-Tree在每个节点存储数据,而B+Tree只有叶子节点存储数据,降低了树的高度,提高了查询稳定性。在MySQL的InnoDB存储引擎中,B+Tree用于索引,因其更高效的空间利用率和查询性能。
摘要由CSDN通过智能技术生成

内存的访问速度比硬盘快,这是毋庸置疑的,根据通常的说法是,内存访问速度是纳秒级(10的-9次方),硬盘的访问速度是微秒级(10的-3次方),相差10万倍,所以,作为数据存储的抽象层来说,会需要尽可能的减少存储的IO次数,来提高自己自己的效率。

B-Tree

原则上,想要降低数据存储的IO次数,那就必须要提高在内存中的运算次数,这时候脑海中会浮现出看书的场景,先打开目录,根据目录中的大标题找到子目录,最后根据子目录找到页码,如果把每次翻阅目录当作一次IO操作,那么,在目录不是很多的情况下,我们可以很快的定位需要的数据,这个就是B-Tree的意义了。B-Tree的数据结构有以下特性:

  1. 每个节点最多有m个孩子。
  2. 除了根节点和叶子节点外,其它每个节点至少有Ceil(m/2)个孩子。
  3. 若根节点不是叶子节点,则至少有2个孩子
  4. 所有叶子节点都在同一层,且不包含其它关键字信息
  5. 每个非终端节点包含n个关键字信息(P0,P1,…Pn, k1,…kn)
  6. 关键字的个数n满足:ceil(m/2)-1 <= n <= m-1
  7. ki(i=1,…n)为关键字,且关键字升序排序。
  8. Pi(i=1,…n)为指向子树根节点的指针。P(i-1)指向的子树的所有节点关键字均小于ki,但都大于k(i-1)

B-Tree
根据上图,假设我们想查找Key值为36所对应的数据,那么从根节点进行查找,首先会将根节点的[17, 35]进行一次内存内的数据比对,判断36>35, 根据指针指向然后在根的右侧枝干进行查找,此时IO操作的次数为1,同样的,在二阶的枝干进行内存内的数据对比,判断指针在左侧枝干,此时IO操作为2,最后在三阶的叶上找到了对应的存储位置,IO操作变为3,至此完成一次完整的查询,共消耗3次IO。
乍看之下,似乎还挺快,但考虑到如果业务数据非常多,层阶也非常多,即树的高度很高,在最差情况下,需要执行层阶次数的IO操作,此外,由于每个枝干上都会有对应的数据映射,会导致查询的效率变的不稳定,时快时慢,对于数据查询其实非常不友好。
所以B+Tree出现了。

B+Tree

相比B-Tree,B+Tree有以下不同:

  1. 非叶子节点只存储键值信息。
  2. 所有叶子节点之间都有一个链指针。
  3. 数据记录都存放在叶子节点中。

B+Tree
可以看到,最大的差别在于,只有叶子节点会保存数据,而其他阶层的枝干,仅仅保留键值,而不保存数据本身,这样的操作使得每个节点能保存的key的数量增多,增加了每一层的节点的宽度,从而降低了树的高度。且由于只有叶子节点存放数据,从而会让查询的效率非常稳定。
所以,这样看来以上两种算法的主要差别在于单个节点的容量上了,放在实际的使用场景,以mysql的innoDB为例子,默认的page大小为16kb(linux默认为4kb),即单个节点内可以存放16kb的数据,一般索引字段往大了算,算BIGINT好了,即单个key为8字节,指针一般是16字节,那么一个节点能存的key的数量为161000/(8+16+16)=400,那么极限情况下,一个3阶的B+Tree可以存放400103*103个Key以及指针,而同样的空间存放数据可能只能存放1/3甚至不到,那相比之下,树的高度会呈现几何倍的下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值