B+树的介绍

B+树的概念
规则:

B+跟B树不同B+树的非叶子节点不保存关键字记录的指针,只进行数据索引,这样使得B+树每个非叶子节点所能保存的关键字大大增加
B+树叶子节点保存了父节点的所有关键字记录的指针,所有数据地址必须要到叶子节点才能获取到。所以每次数据查询的次数都一样
B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针
非叶子节点的子节点数=关键字数(来源百度百科)(Mysql 的B+树)

B+树相比于B树的优点

由于B+树在内部节点上不好含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率;
B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
总结:B+树的I/O次数更少,磁盘读写代价更低,时间更稳定,范围搜索更好

B+树的存在形式

  1. 结点内有n个元素就会n个子结点;每个元素是子结点元素里的最大值或最小值。
  2. 结点内有n个元素就会n+1个子结点;最左边的子结点小于最小的元素,其余的子结点是>=当前元素。

B+树实现
以第一种形式实现

B+树节点参数
protected  int degree;//阶数
    protected  BPlusNode<K,V> parent;//父节点
    protected  int keyNum;//关键字个数
    protected  LinkedList<K> keys;//存放数据项的list,K为key
    protected  boolean isLeaf;//是否为叶子节点

    LinkedList<BPlusNode<K,V>> childList;//存放孩子节点list

    public  BPlusNode(int degree){
        if (degree<3) throw new IllegalArgumentException("The BPlusTree degree must be at least three!");
        this.degree = degree;
        parent=null;
        keys= new LinkedList<>();
        childList= new LinkedList<>();
    }

    //查找
    abstract BPlusNode<K,V> search(K key);

    //删除
    abstract BPlusNode<K,V> delete(K key);
    //插入
    abstract BPlusNode<K,V> insert(K key,V value);

    //上溢
    protected  boolean isOverFlow(){
        return  keyNum >degree;
    }
    //下溢
    protected  boolean isUnderFlow(){

        return  keyNum<Math.ceil(degree/2.0);
    }

```java
    public V  searchData(K key){
        Objects.requireNonNull(key);
        var search =(LeafNode<K, V>) root.search(key);
        if (search.insertIndex<search.entryKey.size()){

            var  searchEntry = search.entryKey.get(search.insertIndex);
            if (searchEntry.key().equals(key)) return searchEntry.value();
        }

        return null;
    }

操作原理

  • 查找操作:从根节点开始,将待查找的关键字与当前节点的关键字进行比较。如果待查找的关键字小于当前节点的最小关键字,则沿着最左边的指针进入下一层节点继续查找;如果待查找的关键字大于当前节点的某个关键字,则沿着相应的指针进入下一层节点。重复这个过程,直到找到目标关键字所在的叶子节点。由于叶子节点之间是有序链表,因此在找到叶子节点后,可以方便地在链表中进行顺序查找,以找到所有匹配的记录。
  • 插入操作:首先进行查找操作,找到合适的叶子节点位置。如果叶子节点未满,则直接将新的关键字插入到叶子节点中,并保持叶子节点的有序性;如果叶子节点已满,则需要对叶子节点进行分裂操作。将叶子节点平均分成两部分,将中间关键字上移到父节点中,并在父节点中插入一个指向新分裂出的叶子节点的指针。如果父节点也已满,则需要对父节点进行类似的分裂操作,直到找到一个未满的父节点或者到达根节点。如果根节点已满,则创建一个新的根节点,将原来的根节点分裂为两个子节点,并将中间关键字插入到新根节点中。
  • 删除操作:先通过查找操作找到要删除的关键字所在的叶子节点。如果该关键字所在的叶子节点中的关键字数量大于最小值(通常为分支因子的一半向上取整),则直接删除该关键字,并保持叶子节点的有序性;如果该叶子节点中的关键字数量等于最小值,且其左右兄弟节点中有一个节点的关键字数量大于最小值,则可以从兄弟节点中借一个关键字过来,或者将兄弟节点与该叶子节点合并。如果兄弟节点的关键字数量也都等于最小值,则需要将该叶子节点与一个兄弟节点合并,并将父节点中对应的关键字删除。如果父节点中的关键字数量小于最小值,则需要对父节点进行类似的调整操作,直到满足 B + 树的结构要求。

优势

  • 高效的查找性能:由于 B + 树的高度相对较低,且叶子节点形成有序链表,因此无论是随机查找还是范围查找,都能够在较短的时间内完成。
  • 支持顺序访问:叶子节点之间的链表结构使得可以方便地进行顺序访问,这对于需要按照顺序处理数据的应用场景非常有利,如范围查询、排序等。
  • 磁盘 I/O 优化:B + 树的节点通常较大,可以容纳多个关键字和指针,使得一次磁盘 I/O 能够读取更多的数据,从而减少磁盘 I/O 的次数,提高系统的整体性能。

应用场景

  • 数据库管理系统:用于存储和索引数据库中的表数据,如 MySQL、Oracle 等数据库都广泛使用 B + 树来实现索引结构,以提高数据的查询效率。
  • 文件系统:在文件系统中,B + 树可以用于存储文件目录信息,快速定位文件的存储位置,提高文件系统的性能。

MySQL中的B+树是怎么实现的:

MySQL 中的 B + 树主要是通过以下方式实现的:

数据结构定义

  • 节点结构:B + 树的节点通常包含多个关键字和对应的数据指针。非叶子节点只存储关键字和指向下一层节点的指针,而叶子节点除了关键字外,还存储了实际的数据记录或者指向数据记录的指针。
  • 关键字有序排列:节点中的关键字按照从小到大的顺序排列。这使得在查找、插入和删除操作时能够快速定位到目标关键字的位置。

查找操作实现

  • 从根节点开始,将待查找的关键字与节点中的关键字进行比较。
  • 如果待查找关键字等于当前节点的某个关键字,则根据该关键字对应的指针找到相应的数据记录。
  • 如果待查找关键字小于当前节点的最小关键字,则沿着最左边的指针继续查找下一层节点。
  • 如果待查找关键字大于当前节点的最大关键字,则沿着最右边的指针继续查找下一层节点。
  • 如果待查找关键字介于当前节点的两个关键字之间,则根据节点中关键字的排列顺序,找到对应的指针,继续查找下一层节点,直到找到目标关键字或到达叶子节点确定不存在该关键字为止。

插入操作实现

  • 首先进行查找操作,找到合适的叶子节点来插入新的关键字。
  • 如果叶子节点未满,则直接将新关键字插入到合适的位置,保持关键字的有序性。
  • 如果叶子节点已满,则需要对该叶子节点进行分裂操作。将叶子节点中的关键字和数据指针平均分成两部分,将中间关键字提升到父节点中,并将新的关键字插入到合适的子节点中。如果父节点也已满,则需要递归地对父节点进行分裂操作,直到找到一个未满的父节点或者到达根节点。如果根节点也已满,则创建一个新的根节点,将原来的根节点分裂成两个子节点,并将中间关键字提升到新的根节点中。

删除操作实现

  • 先通过查找操作找到包含要删除关键字的叶子节点。
  • 如果要删除的关键字所在的叶子节点中的关键字数量大于最小关键字数量限制,则直接从该叶子节点中删除关键字,并调整关键字的顺序以保持有序性。
  • 如果删除关键字后,叶子节点中的关键字数量小于最小关键字数量限制,则需要进行调整操作。可以从相邻的兄弟节点中借调关键字,或者与兄弟节点进行合并操作。如果相邻兄弟节点中的关键字数量足够,则可以将兄弟节点中的一个关键字移动到当前节点中,以保持节点的关键字数量平衡。如果相邻兄弟节点中的关键字数量也不足,则需要将当前节点和兄弟节点合并成一个新的节点,并将父节点中对应的关键字和指针进行相应的调整。如果父节点中的关键字数量小于最小关键字数量限制,可能需要递归地对父节点进行调整操作,直到满足 B + 树的平衡条件为止。

索引组织方式

  • 在 MySQL 中,B + 树索引是基于表中的列来创建的。对于不同的数据类型和索引类型,B + 树的实现细节会有所不同。例如,对于整数类型的索引列,关键字的比较和排序操作相对简单直接;而对于字符串类型的索引列,通常需要根据字符集和排序规则来进行比较和排序。
  • 聚簇索引和非聚簇索引在 B + 树的实现上也有一些差异。聚簇索引的叶子节点直接存储了数据记录,而非聚簇索引的叶子节点存储的是指向数据记录的指针。因此,在使用聚簇索引进行查找时,可以直接获取到数据记录,而使用非聚簇索引查找时,还需要根据指针再去查找相应的数据记录。

MySQL中索引实现原理:

MySQL 中的索引是一种用于提高查询效率的数据结构,其实现原理主要基于 B + 树等数据结构,以下是详细介绍:

B + 树数据结构基础

  • 节点结构:B + 树的节点包含多个关键字和对应的数据指针。非叶子节点仅存储关键字与指向下一层节点的指针,用于引导搜索路径;叶子节点除关键字外,还存储实际的数据记录或指向数据记录的指针。
  • 关键字有序排列:节点内的关键字按从小到大的顺序排列,便于快速查找、插入和删除操作时定位目标关键字。

索引的组织方式

  • 聚簇索引:基于表中某一列或多列组合构建。叶子节点直接存储数据记录,数据在物理存储上按聚簇索引列的值顺序排列。一个表只能有一个聚簇索引,通常主键会被自动设为聚簇索引。如CREATE TABLE语句中使用PRIMARY KEY定义主键时,MySQL 会自动创建聚簇索引。
  • 非聚簇索引:叶子节点存储的是指向数据记录的指针,而非数据记录本身。一个表可以有多个非聚簇索引,可基于表中的其他列创建,用于加速对该列的查询。通过CREATE INDEX语句创建非聚簇索引,如CREATE INDEX index_name ON table_name (column_name);

索引的查找过程

  • 从根节点开始,将查询条件中的关键字与节点中的关键字比较。若相等,则根据指针找到对应数据记录;若小于最小关键字,沿最左边指针找下一层节点;若大于最大关键字,沿最右边指针找下一层节点;若介于两个关键字之间,按顺序找到对应指针继续查找,直至找到目标关键字或确定不存在。

索引的插入与维护

  • 插入操作:先查找合适的叶子节点插入新关键字。若叶子节点未满,直接插入并保持有序;若已满,则分裂节点,将关键字和指针平均分成两部分,中间关键字提升到父节点,新关键字插入合适子节点,若父节点也满,则递归分裂,直至找到未满父节点或到达根节点,根节点满则创建新根节点。
  • 删除操作:先找到包含要删除关键字的叶子节点,若删除后关键字数量大于最小限制,直接删除并调整顺序;若小于最小限制,则需调整,可从相邻兄弟节点借调关键字或合并节点,若兄弟节点关键字数量够,可移动一个关键字到当前节点,若都不足,则合并节点,并调整父节点关键字和指针,若父节点关键字数量不足,需递归调整,直至满足 B + 树平衡条件。

不同数据类型的索引实现特点

  • 整数类型:比较和排序操作简单直接,索引查找效率高。
  • 字符串类型:需根据字符集和排序规则比较排序,字符集不同排序结果和索引结构可能不同,如 UTF-8 和 GBK 字符集对汉字的编码和排序方式有差异。

索引的优缺点及使用注意事项

  • 优点:大大提高查询速度,尤其对大数据量表和复杂查询条件,能快速定位数据,减少磁盘 I/O 操作,提升数据库性能。
  • 缺点:占用额外存储空间,索引需存储关键字和指针等信息;插入、更新和删除操作时,需维护索引结构,增加数据操作时间成本。
  • 注意事项:并非列都适合建索引,如数据重复度高的列建索引效果差;索引列应选常用于查询条件、连接条件和排序条件的列;定期分析查询语句执行计划,根据实际情况调整索引,以保证索引的有效性。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙HarmonyOS 网络请求获取数据Http

注意的是;要为接口返回值指定类型 &#xff0c;以及定义接口数据类型 index.ets import { http } from kit.NetworkKit;interface createAtType {date: number,}interface dataListType {createAt: createAtType;imgUrl: }Component export default struct TabBar {State dat…

2024136读书笔记|《飞鸟集》——使生如夏花之绚烂,死如秋叶之静美

2024136读书笔记|《飞鸟集》——使生如夏花之绚烂&#xff0c;死如秋叶之静美 《飞鸟集》[印]泰戈尔&#xff0c;一本有意思的诗集&#xff0c;中英文对照着读更有意思。“你是谁&#xff0c;读者&#xff0c;百年后读着我的诗&#xff1f;”让我觉得有些久别重逢&#xff0c;忽…

ROS Action

在 ROS 中&#xff0c;Action 是一种支持长时间异步任务的通信机制。与 Service 不同&#xff0c;Action 允许客户端发起一个请求&#xff0c;并在任务执行的过程中不断接收反馈&#xff0c;直到任务完成。这种机制非常适用于可能需要较长时间来完成的任务&#xff0c;比如机器…

约束(MYSQL)

not null&#xff08;非空&#xff09; unique&#xff08;唯一&#xff09; default&#xff08;默认约束&#xff0c;规定值&#xff09; 主键约束primary key&#xff08;非空且唯一&#xff09; auto_increment&#xff08;自增类型&#xff09; 复合主键 check&#xff08…

笔记 | image may have poor performance,or fail,if run via emulation

在Docker Desktop中现象如图&#xff1a; 当你运行 AMD64 平台代码时&#xff08;Intel 和 AMD 芯&#xff09;&#xff0c;你的 Mac 必须模拟其CPU架构&#xff08;因为你自身是ARM&#xff09;。这通常会非常吃性能。 Docker Desktop 警告你在模拟 Intel/AMD x64 CPU 时性能可…

【C++】C++11特性(上)

✨✨欢迎大家来到Celia的博客✨✨ &#x1f389;&#x1f389;创作不易&#xff0c;请点赞关注&#xff0c;多多支持哦&#x1f389;&#x1f389; 所属专栏&#xff1a;C 个人主页&#xff1a;Celias blog~ 目录 一、列表初始化 二、std::initializer_list 三、右值引用和移…

24/11/7 算法笔记 PCA主成分分析

假如我们的数据集是n维的&#xff0c;共有m个数据(x,x,...,x)。我们希望将这m个数据的维度从n维降到k维&#xff0c;希望这m个k维的数据集尽可能的代表原始数据集。我们知道数据从n维降到k维肯定会有损失&#xff0c;但是我们希望损失尽可能的小。那么如何让这k维的数据尽可能表…

JS 实现SSE通讯和了解SSE通讯

SSE 介绍&#xff1a; Server-Sent Events&#xff08;SSE&#xff09;是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比&#xff0c;SSE提供了更高效和实时的数据推送机制。 SSE基于HTTP协议&#xff0c;允许服务器将数据以事件流&#xff08;…

C/C++每日一练:查找链表的中间节点

链表&#xff08;Linked List&#xff09; 链表是一种线性数据结构&#xff0c;由一系列节点&#xff08;Node&#xff09;通过指针链接在一起。与数组不同&#xff0c;链表中的元素在内存中不需要连续存储&#xff0c;每个节点包含两部分&#xff1a; 数据部分&#xff1a;存…

对称加密与非对称加密:密码学的基石及 RSA 算法详解

对称加密与非对称加密&#xff1a;密码学的基石及 RSA 算法详解 在当今数字化的时代&#xff0c;信息安全至关重要。对称加密和非对称加密作为密码学中的两种基本加密技术&#xff0c;为我们的数据安全提供了强大的保障。本文将深入探讨对称加密和非对称加密的特点、应用场景&…

PH47代码框架全局函数及功能类

PH47代码框架全局函数及功能类 概述 全局函数及功能类体系是PH47框架当中除了4个逻辑层之外最重要的组成部分之一&#xff0c;它们可以在 整个PH7 代码框架及用户代码中使用。常用全局函数及功能类为 PH7 代码框架提供了最常用和最基础的功能实现。 全局函数主要包含了对时间…

力扣 LeetCode 203. 移除链表元素(Day2:链表)

解题思路&#xff1a; 方法一&#xff1a;头节点和非头节点分开处理 方法二&#xff1a;定义一个dummy虚拟节点&#xff0c;后面的节点就可以采用相同的处理方式 注意&#xff1a; cur需要指向要删除的节点的上一个节点&#xff0c;因为要越过这一个被删除的节点 class Sol…

IEC60870-5-104 协议源码架构详细分析

IEC60870-5-104 协议源码架构 前言一、资源三、目录层级一二、目录层级二config/lib60870_config.hdependencies/READMEexamplesCMakeLists.txtcs101_master_balancedcs104_client_asyncmulti_client_servertls_clienttls_server说明 make这些文件的作用是否需要导入这些文件&a…

turbo c 2.0 画螺栓

代码; #include<graphics.h> void bolt(x0,y0,d,l) int x0,y0,d,l; {int x1,x2,x3,x4,x5,x6,x7,x8;int y1,y2,y3,y4,y5,r1,r2,b,c;if(l>2*d) b2*d;else b1;r11.5*d;r20.38*d;c0.1*d;x1x0-0.7*d;x2x0-0.61*d;x3x0-0.32*d;x4x00.8*d;x5x0l-b;x6x0l-c;x7x0l-0.05*d;x8x0…

网络服务综合项目-博客

一、运行环境&#xff1a; 主机主机名系统服务192.168.31.128Server-WebLinuxWeb192.168.31.129Server-NFS-DNSLinuxNFS 二、基础配置&#xff1a; 配置主机名开启防火墙并配置部分开启selinux并配置服务器之间使用ntp.aliyun.com进行时间同步服务器之间实现ssh免密登录 三…

leetcode86:分隔链表

给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示例 1&#xff1a; 输入&#xff1a;head [1,4,3,2,5,2], x 3 输出&am…

Android Mobile Network Settings | APN 菜单加载异常

问题 从log看是有创建APN对应的Controller&#xff08;功能逻辑是ok的&#xff09;&#xff0c;但是Mobile Network Settings无法显示&#xff08;UI异常&#xff09;。 日志分析 看似APN 菜单已经创建了&#xff0c;实际上并没有显示。 11-12 07:01:28.150 8773 8773 D Pr…

上海市计算机学会竞赛平台2020年4月月赛丙组永恒的生命游戏

题目背景 2020年4月11日&#xff0c;英国数学家 约翰霍顿康威&#xff08;John Horton Conway&#xff09;因为新型冠状病毒肺炎不幸逝世。他在群论、数论、代数、几何拓扑、理论物理、组合博弈论和几何等领域&#xff0c;都做出了重大贡献。他的离去是人类文明的损失。他最著…

FS8x 功能安全

fail-safe是电独立的和物理隔离的。fail-safe由自己的参考电压和电流提供,有自己的振荡器,有重复的模拟路径以最小化常见的故障,并有LBIST/ABIST来覆盖潜在故障。fail-safe根据设备部件号提供ASIL B或ASIL D遵从性。除非另有规定,fail-safe定时来自故障安全振荡器,其精度为…

项目模块十七:HttpServer模块

一、项目模块设计思路 目的&#xff1a;实现HTTP服务器搭建 思想&#xff1a;设计请求路由表&#xff0c;记录请求方法与对应业务的处理函数映射关系。用户实现请求方法和处理函数添加到路由表&#xff0c;服务器只接受请求并调用用户的处理函数即可。 处理流程&#xff1a; …