我们在日常中经常操作数据库,mysql数据库是常用的数据库之一,支持多种索引类型,如B+Tree,哈希索引,全文索引等。这次主要研究的就是常用的B+Tree也叫B+树。
什么是B+树?
B+ 树是一种树数据结构,通常用于数据库和操作系统的文件系统中。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入,这与二叉树恰好相反。但是光说概念无疑是晦涩的,下面就来看一下为什么B+树可以作为数据库的主要索引之一。
索引的本质
MySQL官方对索引的说明是索引是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。为什么这里要讲查询算法和数据结构呢?因为之所以要建立索引,其实就是为了构建一种数据结构,可以在上面应用一种高效的查询算法,最终提高数据的查询速度。
要了解数据库索引的底层原理,我们就得先了解一种叫树的数据结构,而树中很经典的一种数据结构就是二叉树!所以就从二叉树到平衡二叉树,再到B树(B-树),最后到B+树来一步一步了解数据库索引底层的原理
二叉树
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。二叉树有如下特性:
1、每个结点都包含一个元素以及n个子树,这里0≤n≤2。
2、左子树和右子树是有顺序的,次序不能任意颠倒。左子树的值要小于父结点,右子树的值要大于父结点。
那么假设现在有这样一组数[35 27 48 12 29 38 55],顺序的插入到一个数的结构中,得到的结果就会是下面这样。

但是这样的数据对于二叉树有一个问题就是,假如每次插入的数据都比上一个要大,那么这棵树的长度就会越来越大,因为他始终都要在右边插入,这样就变成了一个类似于队列的结构,这无疑是会严重影响查询速度的,所以,为了加快查询速度,就在二叉树的基础上衍生出了平衡二叉树
平衡二叉树
平衡二叉树是一种特殊的二叉树,所以他也满足前面说到的二叉树的两个特性,同时还有一个特性:
它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
这样这棵树就始终满足二叉树的几个特性而保持平衡,树也不会退化为线性链表了,需要查找一个数的时候就能沿着树根一直往下找,这样的查找效率是很快的,查询次数也会大幅度缩减。
但是数据库的数据是存储于硬盘中的,也就是说每次我们查找读取数据,是要通过磁盘的IO进行读写,这个读的效率是固定并且损耗性能的,暂时无法突破,那么假如数据量过于庞大,我们理论最坏需要进行查询的次数变的越来越多的话,就会导致效率变得很低,那么在这个问题上,又进行了优化,我们可以一次多查询一些数据,或者说让树的每一层可以存储更多的节点,这就有了B-Tree(B树)
B-Tree
那B-Tree有哪些特性呢?一棵m阶的B-Tree有如下特性:
1、每个结点最多m个子结点。
2、除了根结点和叶子结点外,每个结点最少有m/2(向上取整)个子结点。
3、如果根结点不是叶子结点,那根结点至少包含两个子结点。
4、所有的叶子结点都位于同一层。
5、每个结点都包含k个元素(关键字),这里m/2≤k<m,这里m/2向下取整。
6、每个节点中的元素(关键字)从小到大排列。
7、每个元素(关键字)字左结点的值,都小于或等于该元素(关键字)。右结点的值都大于或等于该元素(关键字)。
示例如下:

从这个图中我们能看出,B-Tree的查询效率好像也并不比平衡二叉树高。但是查询所经过的结点数量要少很多,也就意味着要少很多次的磁盘IO,这对性能的提升是很大的。
B-Tree的元素就是类似1、2、3这样的数值,但是数据库的数据都是一条条的数据,如果某个数据库以B-Tree的数据结构存储数据,普通的B-Tree的结点中,元素就是一个个的数字。B-Tree把元素部分拆分成了key-data的形式,key就是数据的主键,data就是具体的数据。这样我们在找一条记录的时候,就沿着根结点往下找就ok了,效率是比较高的。

但是IO在读取硬盘的文件的时候也是有限制的,它一次只能读取约4KB的数据,在结点中存储数据无疑也是要浪费IO的读写的,假如一条记录的索引对应的数据过大,大于了4KB的话,那么这一次IO的读写就无法读取其他的记录,导致在树的一层可能会耗费多次IO的读,所以在这基础上又进行了优化,就有了B+Tree(B+树)。
B+Tree
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构。B+Tree与B-Tree的结构很像,但是也有几个自己的特性:
1、所有的非叶子节点只存储关键字信息。
2、所有卫星数据(具体数据)都存在叶子结点中。
3、所有的叶子结点中包含了全部元素的信息。
4、所有叶子节点之间都有一个链指针。

B-Tree 和 B+Tree的选择
在讲这两种数据结构在数据库中的选择之前,我们还需要了解的一个知识点是操作系统从磁盘读取数据到内存是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理: 当一个数据被用到时,其附近的数据也通常会马上被使用。
预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k)。
那么B-Tree和B+Tree该如何选择呢?都有哪些优劣呢?
B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。
由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。
由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。
鉴于以上的比较,所以在常用的关系型数据库中,都是选择B+Tree的数据结构来存储数据
相关推荐
从AMBA到USB:手把手教你评估和选择Synopsys DesignWare里的免费商用IP
本文详细介绍了如何评估和选择Synopsys DesignWare中的免费商用IP,从AMBA到USB等关键模块。通过技术参数核对、验证环境评估和集成注意事项,帮助工程师高效利用这些经过硅验证的商业级IP,提升SoC设计效率。文章还探讨了免费IP与付费IP的边界策略,避免常见陷阱。
浅析Mysql索引Innodb及底层存储结构B+树
前言 最近博主在学习mysql索引相关知识,看了很多博客,公开课然后自己总结一下,最近的收获吧。本文从二叉树->平衡二叉树->B树(有同学读B减树,是不正确的) ->B+树 再到B+树在Myisam和Innodb中的体现形式,会提到索引失效的情况,以及创建索引时的一些注意事项及其原理。采用大量的图片+部分文字更加清晰的描述。其中部分图片来源于咕泡学院公开课。 准备 提到my...
【手把手教学】YOLOv13的Dilated Reparam Block (DRB) 实现细节与优化技巧
DRB(Dilated Reparam Block)是一种创新的卷积神经网络模块,通过多分支膨胀卷积和结构重参数化技术显著提升模型性能。训练阶段使用不同膨胀率和卷积核大小的并行分支增强特征提取能力,推理阶段则将这些分支融合为单一高效的大核卷积。该方法成功解决了大核卷积的计算复杂度和训练困难等问题,在保持推理效率的同时,使模型准确率提升8.56%,mAP暴涨12.33%。DRB的核心在于训练时复杂、推理时简单的设计哲学,以及膨胀卷积的多尺度特征提取能力,为CNN性能优化提供了新的思路。
MySQL性能优化浅析及线上案例
由于order by后边没有索引,就看where条件中是否有合适的索引,查询选择器选定rx_status这个单列索引,而rx_status=5这个条件下限制的数据行在索引中是连续,即使需要的rx_id不在索引中,再回主键聚簇索引也来得及,由于order by后边没有索引,所以走磁盘级别的排序filesort,高峰积压的时候处方就1万到2万,跑到了100ms,白天低谷的时候几百单也就20ms。,由于外部的ID有的是数字有的是字符串,因而导致索引一会可以走到,一会走不到,最终导致了性能的不稳定。
浅析MySQL 8.0直方图原理
本文将对直方图概念进行介绍,借助举例描述直方图的使用方式,对创建/删除直方图的原理进行浅析,并通过例子说明其应用场景。
浅析innoDB索引结构
浅析innoDB索引结构 No.1 引言 在上两期分享了innoDB锁机制,innoDB存储结构,相信大家对innoDB也有了一定的了解, 今天将在上期存储结构的基础上,详细聊聊我们平时使用较多的innoDB索引是怎么回事? No.2 课前提问 为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?没有主键怎么办? 为什么非主键索引结构叶子节点存储的...
MySQL InnoDB 存储引擎原理浅析
MySQL InnoDB 存储引擎原理浅析 版权说明:本文章版权归本人及博客园共同所有,转载请标明原文出处(https://www.cnblogs.com/mikevictor07/p/12013507.html),以下内容为个人理解,仅供参考。 前言: 本文主要基于MySQL 5.6以后版本编写,多数知识来着书籍《MySQL技术内幕++InnoDB存储引擎》,本文章仅记录个人认为比较重要的部分,有兴趣的可以花点时间读原书。 今年的多数学习知识只写在笔记里,较为零散,最近稍有时间整理出来,分享...
大厂学长发给我的416页Mysql学习笔记,分享给大家
在之前校招面试中,mysql 被问到的频率是真的高,自以为还算精通,经不住面试官刁钻的问题。为了快速补齐,网络上找了不少资料。反而陷入学习凌乱…… 无奈求助一个已经进入大厂的学长,因为他时间比较忙,就塞给了我一本超详细的学习笔记,让我按索引查看不熟悉的地方。真的是超级全面,覆盖了Mysql的所有知识点。现在拿出来分享给大家。一起进步! 整整26个篇幅416页的内容,全程干货!包含最基础的安装、常用命令、SQL分类;介绍mysql中常⽤的数据类型;mysql类型和java类型对应关系; 数据类型选择的⼀些
MySQL中为什么要使用索引合并(Index Merge)?
本文介绍了索引合并(Index Merge)包含的三种类型,即交集(intersection)、并集(union)和排序并集(sort-union),以及索引合并的实现原理、场景约束与通过案例验证的优缺点。
MySQL 学习资源整理
MySQL也有了几年了,说不出来个所以然,认知比较肤浅。所以需要加深学习呀,这里是学习过程中收集的一些好的资源,希望大家共同进步了。不是很系统的整理,看到了就记录了下来。 博客前辈们的博客就是他们成长的足迹。 DimitriK’s (dim) 玄惭 阿里 何登成 阿里 叶金荣 知数堂 姜成尧 网易 杨奇龙 支付宝 penglixun 阿里 王朝阳 大师兄 吴老师 知数堂 黄杉 周振兴 一个
学习总结与分享-MySQL的优化(完结篇)
在日常代码开发中,我们总是要写各种各样的sql语句,一段程序或者说一次客户端与服务端的交互,最能影响执行速度的就是网络的传输和底层数据的存取等。。那么底层数据的存取如果是使用的是磁盘存储的关系型数据库,那么就是依靠sql语句了,所以,一个或者一组sql的执行效率,直接的影响到了程序的执行速度和用户体验,所以我们在编程时,要学会sql的优化,最大化的优化sql的执行时间,这样不仅可以增加执行速度,还...
学习总结与分享-浅析java的多态与策略模式
多态,是java三大面向对象的特性之一,其他还有封装和继承,有时人们也会将抽象算进去,称为四大特性。在日常写代码时,我们基本每天都在看到使用到多态,那么,什么是多态呢,又该怎么正确使用呢,这就是今天要去研究的了。。 1.什么是多态: 其实提到多态就不得不提到继承,因为要实现多态,首先第一点必须要有继承一个父类,然后重写或实现其中的方法,最后用最简单的一句话就是:父类型的引用指向子类型的对象...
学习总结与分享-数据库的事务与锁入门
这次的事务和锁研究,主要是MySQL数据库的innodb引擎,说到数据库,就免不了要说事务和锁机制,这是数据库最重要的组成部分。 什么是事务? 事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。(摘自百科) ...
学习总结与分享-Spring IOC容器的常用注解与生命周期
经过上次的学习,已经初步的了解了Spring IOC的简单容器是如何编写的,也大体明白了Spring IOC容器的作用与原理,那么如何才能使用好Spring IOC使其可以为我们正确的生成实体bean,正确的注入属性呢。 Spring 基于xml文件方式生成bean: 我们上次的学习就是通过配置文件的方式自己手写的简单IOC容器,而Spring已经为我们封装好了方法,只需要通过正确的xml配置,就...
学习总结与分享-spring篇之IOC(控制反转)浅析
概述 IOC 的作用: 解耦、单例缓存、Bean生命周期管理、父子容器 IOC 工作要经历2个过程: 启动预加载BeanDefination、实例化对象且缓存单例,传统BeanFactory的实现类是懒加载(loadClass时再实例化bean),而web容器实现是预加载(启动和实例化一起进行)。但是BeanDefination都是预加载的。 IOC的作用 1、解耦: 实现了类与类依赖关系的解耦,...
学习总结与分享-常用Map集合之HashMap原理浅析
Map是一种以(key,value)键值对的形式来存储数据的集合体系,其中HashMap也是这个体系中最常用的集合之一,他的查询速度与增删的速度都十分的快,存取是无序的,并且其中键值对中的键(key)值不能重复,重复则替换之前的value值,那么就引申出几个问题。 1.常见的集合还有哪些? LinkedHashMap,与HashMap的区别为他的存取顺序是有序的,因为他的 HashTa...
学习总结与分享-MySQL的MVCC(多版本并发控制)浅析
我们在平时编码操作数据库时,通常会有一个事务A读取一行数据,而又有另一个事务B需要写同一条数据,而为了保证事务A在每次读取时保持一致性和原子性,在传统的事务的锁机制下,这肯定是不允许的,事务B需要等待事务A执行结束后才可以执行,而当类似的需求并发过多的时候,就很容易产生锁阻塞、死锁或者事务一直在等待执行过慢导致报错等等情况,所以数据库就使用了MVCC这个概念来解决事务在并发下的效率问题。 什么是M...
学习总结与分享-设计模式之代理模式入门
设计模式 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。(-----摘自百度百科) 人们所熟知的设计模式共有23种,这次要研究的是其中的一种在日常开发中很常见的模式之一,代理模式。...
学习总结与分享-JVM虚拟机类加载过程
一、什么是类的加载 java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM中。其中类装载器的作用其实就是类的加载。 二、类加载的过程 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们的顺序如下图所示: 中类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。在这五个阶段中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后开
学习总结与分享-dubbo的了解与初步使用
什么是dubbo? Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。 Dubbo是阿里巴巴SOA服务化治理方案的核心框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。 通俗来讲dubbo是一种服务与服务之间的通信方式,是为了解决分布式架构服务器所产生的一些问题的框架。 什么...
CH340C+RT9013+MINI USB接口板 AD设计硬件原理图+PCB文件.zip
CH340C+RT9013+MINI USB接口板 AD设计硬件原理图+PCB文件,ALTIUM设计的2层板设计,包括完整的原理图和PCB文件,主要器件如下:Library Component Count : 12Name Description----------------------------------------------------------------------------------------------------CAP CapacitorCC2640EM CC2630 ModuleCH340 CH340 USB 2 UARTCON11 Connector 11pinsCON12 Connector 12pinsCON3X2 Connector 5*2LED LEDRES ResistorRT9013 RT9013 3.3VSWITCH switch 6*6USB1 USB ConnectorsXDS110-Lte XDS110-Lite Target Interface
AVRDUDESS-2.13-setup.exe.zip
AVRDUDESS-2.13-setup.exe.zip
258




被折叠的 条评论
为什么被折叠?



