数据结构 - B+树(B树)

目录

1、B+树

2、B+树 VS B树

3、Mysql为什么选择B+树?


    理解B+树的数据结构一定在理解了树、平衡二叉搜索树的基础上。再梳理一下,平衡二叉树是为了让树本身更加的”丰满“,近似于满二叉树(或者完全二叉树),降低树的层高【查询效率与树的层高有关】,防止极端情况树退化成时间复杂度为O(N)的链表。二叉查找树是当每个节点做一次判断,就可以选择左子或右子树进行查询,每次讲数据查询范围缩小为原来的一半。 基于平衡二叉查找树,整个树的读写的时间复杂度近似O(logN),效率是非常高的,之前分析过当N为42亿次时,O(logN)查询次数是32,而O(N) 查询次数是42亿次。平衡二叉查找树有:AVL树(自平衡二叉查找树)、树堆(Treap)、伸展树,以及工程上经常使用的高性能-红黑树。

    我们想到数据库(Mysql/Oracle)就会想到B树、B+树,反之也是一样的,如果只是基于性能考虑红黑树完全够了。但是数据库需要存储大量的数据,并且一般需要保证事务(ACID特别是持久化),即数据库的数据必须落地(磁盘)。基于计算机的内存寻址查询的性能是纳秒级别的,而磁盘寻址的查询性能是毫秒级别的,性能对比是万倍,十万倍的差距。所以需要控制查询磁盘的次数,即控制树的高度,显然平衡二叉查找树是不行的,所以需要将二叉变成多叉,B+树本身就是多路平衡查找树。从磁盘中获取数据到缓存中,则需要涉及到操作系统的缓存页问题,一般缓存页为4K左右。我们要完全利用其特性,所以Mysql中的多路默认为1200。

    此时,如果存储17亿的数据,层高仅为4。 如果考虑到根节点的数据存储在内存中,那么最多磁盘寻址三次,如果经常查询的数据,第二层数据节点的缓存页也在内存中,那么只需要最多磁盘寻址两次。数据到底在磁盘中还是内存中,Mysql使用了LRU的缓存淘汰算法,并且将整个链表分成 5/8 的old区和 3/8的young区域(用于防止某一次的全表扫描查询操作导致缓存命中率降低)。

1、B+树

    站在数据结构的角度,看看B+树的特性如下(下面的m就是多路平衡查找树中的多字):

  • 每个节点的子节点个数不能超过m,也不能小于 m/2.
  • 根节点的子节点个数可以小于 m/2,这是特殊于上一条的点
  • m叉树只存储索引,并不存储真实的数据,这个与跳表一样
  • 通过链表将叶子节点连接在一起,这样就可以按照区间查询
  • 一般情况下,根节点会被存储在内存中,其他节点存储在磁盘中(依据上面分析的数据库缓存淘汰算法)

平衡二叉查找树为了维持:查找、平衡两个特性,当发生新增、删除操作时,需要树本身也维持这两个特性,AVL树本身需要对节点进行左右旋转。而红黑树更加复杂,除了旋转还需要更改节点的颜色。B+树本身也不例外,只是树的高度已经非常低了,并且每个节点内部的个数非常大。此时左右旋转已经不适用了,对应新增删除需要进行数据页的分裂和合并,用于满足节点个数为【m/2,m】。

    下面是https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html中,degree为3、7的时候生成的两棵B+树(自行脑补 1200路的样子):

 

2、B+树 VS B树

    B-树本身就是B树,都是翻译写法的原因导致我也是误导了很久,哈哈。B树在数据库中的使用也非常广泛,比如 MongoDB、Oracle。下面是B树区别于B+树的特点:

  • B+树中的节点不存储数据,只是索引(即数据全部在叶子节点上),而B树中的节点存储数据
  • B树中的叶子节点,没有使用链表指针链接
  • 即:B树只是一棵每个节点的子节点个数不能小于m/2的 m叉树

数据可以存储在非叶子节点中,所以使用链表进行链接本身没有意义(会很混乱)。数据不存储在叶子节点上,那么查询一个数据的时候,可能在根节点就查询返回了,可能在第2层查询返回了,也可以能在叶子节点(最高处)查询返回,那么查询本身就兼容了查询的最好、最坏时间复杂度。 而B树每次查询都需要到叶子节点,即B+树查询性能是稳定的

 

3、Mysql为什么选择B+树?

    个人理解:需求梳理 -> 功能(需要支持的方法)+ 性能 -> 算法 + 数据结构

    Mysql本质是数据库,需要存储大量的数据和查询,并且Mysql基本都会使用InnerDB引擎,支持事务特性ACID。进行梳理前还需要考虑一个历史因素,数据库是一个“古老”的东西,B+树出现在1972年,而跳表出现在我出生那一年(1989)。梳理一下需要满足的功能:

1、sql:create、update、delete、select

    即数据库本身需要支持大量的读写操作,那么选择的数据结构本身需要支持快速的读写数据结构,时间复杂度不能太高。

    读写时间复杂度为O(logN) 的数据结构都可以考虑,此时维护可以基于二分查找的有序数组,不能满足大量的写操作(非静态数据)。只是Mysql的B+树内部数据节点(数据页),内部查询可以理解成二分查找。

    读写时间复杂度为O(logN)的有红黑树、跳表,只是红黑树本身比较适合存储在内存中使用。读写时间复杂度近似O(1)的散列表也是可选的。

2、等值查询:select * from table where id = 1

    基于等值查询,有序数组、红黑树、跳表、散列表本身都是可行的

3、范围查询:select * from table where id > 30

    基于范围查询红黑树需要每次都从根节点查询,即满足条件的有1000条则要执行1000次根节点开始查询,执行 1000 * O(logN)。而B+树利用叶子节点使用链表进行存储,查询下一个节点的时间复杂度是O(1).

    散列表通过散列函数查询对应的值,本身要求散列函数计算的值越随机、越散列越好,跟支持有序刚好相反(基于LinkedHashMap的 散列表+双向链表此处是可行的)。

    跳表本身是满足范围查询的。

4、order by(group by)支持排序、join操作、count(*)

    这些都是在内存中,基于 join buffer、sort buffer(文件排序)等实现,只是这些都依赖数据结构的查询速度。

 

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
B树是一种常用的索引数据结构,是从二叉查找树、平衡二叉树演化而来的。它被广泛应用于数据库系统中,包括MySQL中的InnoDB存储引擎。B树的特点是具有多个子节点,可以在每个节点中存储多个键值对,而不仅仅是一个键和一个值。通过使用B树索引,数据库可以更高效地存储和查找数据。 B树索引在InnoDB中的实现方式是,将每个节点作为一个数据页。从数据页的角度来看,B树查询过程是按照一定的规则进行的。查询过程从根节点开始,根据键的值进行比较,决定向左子节点还是向右子节点继续搜索。在每个节点中,根据节点存储的键值对进行比较,直到找到匹配的键值对或者确定无法找到匹配的键值对为止。 B树的优点在于可以提供较快的查询性能,因为B树具有平衡性,所以它的高度相对较低,每次查询只需经过几个节点即可找到目标数据。此外,B树还支持高效的插入和删除操作,因为它的平衡性可以保持树的结构相对稳定。 总之,B树是一种常用的索引数据结构,通过使用多个子节点和在节点中存储多个键值对的方式,可以提供高效的数据存储和查询性能。它在数据库系统中得到广泛应用,包括MySQL的InnoDB存储引擎。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [MySQL索引-B+树(讲得通透)](https://blog.csdn.net/zsz0147/article/details/117985568)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [MYSQL索引数据结构----B+树](https://blog.csdn.net/sanylove/article/details/127245540)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值