b+树时间复杂度_第15期:索引设计(索引组织方式 B+ 树)

ff1d35889f4ee9a442f69dea51c4e09b.png

谈到索引,大家并不陌生。索引本身是一种数据结构,存在的目的主要是为了缩短数据检索的时间,最大程度减少磁盘 IO。

任何有数据的场景几乎都有索引,比如手机通讯录、文件系统(ext4xfsfs)、数据库系统(MySQLOracle)。数据库系统和文件系统一般都采用 B+ 树来存储索引信息,B+ 树兼顾写和读的性能,最极端时检索复杂度为 O(logN),其中 N 指的是节点数量,logN 表示对磁盘 IO 扫描的总次数。

MySQL 支持的索引结构有四种:B+ 树,R 树,HASH,FULLTEXT。

本篇简单介绍下 B+ 树,下一篇讲 MySQL 常用的两种引擎 MyISAM 和 InnoDB 的 B+ 树索引实现,其余的后面会讲到。

一、什么是二叉树?

再讲什么是 B+ 树之前,先来了看下什么是二叉树。

树本身是一种数据存储结构,因为类似现实生活中的树而命名。

一个看似没有修剪过的树,其实这是一棵二叉树,每个节点最多有两个子节点

374fa1888ecd553d121ff9fad5dc0d84.png

树相关的基础概念:

拿图 1 这棵树举例说明:

  • 根节点:6 为根节点,根节点没有父节点,有儿子节点,一般叫做 ROOT 节点;
  • 儿子节点:8 和 4 是 6 的儿子节点,4 是左儿子,8 是右儿子;
  • 父节点:6 是 4 和 8 的父节点,父节点是儿子节点的上层节点;
  • 叶子节点:4 和 5 是叶子节点,叶子节点指的是除根节点外没有儿子的节点;
  • 兄弟节点:8 和 4 互为兄弟节点,因为有共同的父亲 6。10,9,7 三个节点没有兄弟,都只有一个儿子;
  • 层数:一棵树的节点层数。图 1 层数为 6;
  • 高度:自下向上遍历,从叶子节点遍历到根节点所需要的节点数量。叶子节点 5 到根节点遍历 7,9,10,8,6,这棵树的高度为 5;
  • 深度:自上而下遍历,从根节点到叶子节点遍历所需要的节点数量,同样,这棵树的深度也是 5;
  • 高度和深度一般以 0 开始计算,当然也有按照从 1 开始计算的;
  • 平衡因子:某节点的左子树与右子树深度的差值,一般结果为绝对值。如果任何一个子树不存在,按照 0 处理。比如节点 10 的平衡因子就是 3;

图 1 是一颗非常普通的树,非常容易退化为一张链表。如果把图 1 换成如下图, 根节点就变为 4,6 退化为 4 的儿子节点,这棵树就退化为一张链表。

a7c094e3546dbe90b16f53046b6d3487.png

链表的查找非常慢,只能按照节点顺序查找,每个节点都遍历一遍,时间复杂度为 O(n),无法随机查找。

二、平衡二叉树(AVL)

那对图 1 进行下改造,把数据重新节点重新连接下,图 2 如下:

aeff57befdfe827ebd1e9a5c6a3a3123.png

图 2 可以看到以下特性:

1. 所有左子树的节点都小于其对应的父节点(4,5,6)

2. 所有右子树上的节点都大于其对应的父节点(8,9,10)>(7);(6)>(5);(10)>(9);

3. 每个节点的平衡因子差值绝对值 <=1;

4. 每个节点都符合以上三个特征。

满足这样条件的树叫平衡二叉树(AVL)树。

问:那再次查找节点 5,需要遍历多少次呢?

由于数据是按照顺序组织的,那查找起来非常快,从上往下找:7-5,只需要在左子树上查找,也就是遍历 2 次就找到了 5。假设要找到叶子节点 10,只需要在右子树上查找,那也最多需要 3 次,7-9-10。也就说 AVL 树在查找方面性能很好,最坏的情况是找到一个节点需要消耗的次数也就是树的层数, 复杂度为 O(logN)

如果节点非常多呢?假设现在有 31 个节点,用 AVL 树表示如图 3:

bc011b207b00898f4b5a19901b60f077.png

图 3 是一棵高度为 4 的 AVL 树,有 5 层共 31 个节点,橙色是 ROOT 节点,蓝色是叶子节点。对 AVL 树的查找来看起来已经很完美了,能不能再优化下?比如,能否把这个节点里存放的 KEY 增加?能否减少树的总层数?那减少纵深只能从横向来想办法,这时候可以考虑用多叉树。

三、B 树

B 树是一种多叉的 AVL 树。B-Tree 减少了 AVL 数的高度,增加了每个节点的 KEY 数量。

B 树的特性:(m 为阶数:结点的孩子个数最大值)

1. 树中每个节点最多含有 m 个孩子节点 (m>=2);

2. 除根节点和叶子结点外,其他节点的孩子数量 >=ceil(m / 2);

3. 若根节点不是叶子结点,最少有两个孩子

  • 特殊情况:没有孩子的根结点,即根结点为叶子结点,整棵树只有一个根节点;

4. 每个非叶子结点中包含有 n 个关键字信息:(n,P0,K1,P1,K2,P2,......,Kn,Pn) 其中:

  • Ki (i=1...n) 为关键字,且关键字按顺序升序排序 K(i-1)< Ki
  • Pi 为指向儿子节点的指针,且指针 P(i-1) 指向的儿子节点里所有关键字均小于 Ki,但都大于 K(i-1)
  • 关键字的个数 n 必须满足:[ceil(m / 2)-1]<= n <= m-1
  • 如果一个结点有 n 个关键字,那么该结点有 n+1 个分支。这 n+1 个关键字按照递增顺序排列
  • 所有叶子结点都出现在同一层,是所有遍历的终点位置

按照这个要求,把图 3 简单变为一棵 B 树,见图 4:

3373f7d0f76d1a53a16657c83840c24e.png

图 4 是一棵 4 阶 B 树,总共有 11 个节点,节点数比图 3 少了 20 个;层数为 3,比图 3 少了两层。实际应用中,每个最小单元不是 KEY,而一般是按照块(BLOCK)来算。比如磁盘文件系统 EXT4 每块 4KB;数据库比如 PostgreSQL 是 8KB,MySQL InnoDB 是 16KB, MySQL NDB 是 32KB 等。

所以再次理清图 4 的 B 树,变为图 5:

d21260a9067108519f63299ea1c06c5d.png

图 5 每个节点的基本单元是一个磁盘块(BLOCK,默认 4KB),根节点含有一个键值,其他节点含有 3 个键值,每个磁盘块包含对应的键值与数据。

比如现在要读取 KEY 为 31 的记录:先找到根节点磁盘块(1),读入内存。(第一次 IO);关键字 31 大于区间(16,),根据指针 P2 找到磁盘块 3,读入内存(第二次 IO);31 大于区间(20,24,28),根据指针 P4 读取磁盘块 11(第三次 IO),在磁盘块 11 中找到 KEY 为 31 的记录,返回结果。这期间有三次磁盘 IO 的读取。可以明确看到,B 树相对于 AVL 树,减少了树的节点数与树的深度,减少了磁盘 IO。

看到这里其实有一个问题,三次 IO,前两次 IO 其实从磁盘读取了不必要的数据,因为只用比较 KEY,所以非叶子节点对应的 DATA 完全没有必要,如果 DATA 很大,那完全是浪费内存资源。考虑下能否把非叶子节点的 DATA 拿掉?

四、B+ 树

B+ 树是对 B 树的一个小升级。大部分数据库的索引都是基于 B+ 树存储的。MySQL 的 MyISAM 和 InnoDB 引擎的索引都是基于 B+ 树存储。

B+ 树最大的几个特点:

1. 非叶子节点只保留 KEY,放弃 DATA;

2. KEY 和 DATA一起,在叶子节点,并且保存为一个有序链表(正序,反序,或者双向);

3. B+ 树的查找与 B 树不同,当某个结点的 KEY 与所查的 KEY 相等时,并不停止查找,而是沿着这个 KEY 左边的指针向下,一直查到该关键字所在的叶子结点为止。

那对图 5 的 B 树做一个调整,变为以下 B+ 树,见图 6:

7fa4eb68d0ee3cbe440c4e89bb769804.png

图 6 是一棵 6 阶 B+ 树。不同于图 5,非叶子节点不再包含除了主键外的数据,数据全部放在叶子节点,并且所有叶子节点存放在一个单向链表里,当然也可以双向链表。可以看到,B+ 树同时具有平衡多叉树和链表的优点,即可兼顾 B 树对范围查找的高效,又可兼顾链表随机写入的高效, 这也是大部分数据库都用 B+ 树来存储索引的原因。

本篇是为了下一篇介绍 MySQL 的两种常用引擎:MyISAM 和 InnoDB 索引结构做了一个铺垫,下期见。


关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

ad409969d4a8d3fd09409fa49840f386.png

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

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

相关文章

结合控制台程序和K8S的CronJob完成定时任务

前言 老黄前段时间遇到了一个数据清洗的需求&#xff0c;其实就是每天凌晨把昨天的数据清洗一遍&#xff0c;归归类。这是一个比较典型的定时任务的处理场景。定时任务可以说就一把利器&#xff0c;几乎每个公司都离不开&#xff0c;它的应用场景也不在少数&#xff0c;比如&am…

数据结构——图-有向带权图的邻接表基础

#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型&#xff08;char&#xff09; #define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表 {int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置int weight; …

vs里面mfc是什么_最近!一大批人正在前往文安,究竟发生了什么?

阅读本文前&#xff0c;请您先点击上面蓝色字体“文安家乡群”再点击“关注”&#xff0c;这样您就可以加入文安家乡群了。最近&#xff0c;文安的火车站汽车站&#xff0c;来了一大批外地人&#xff0c;挤爆了文安车站…究竟发生了什么事儿&#xff1f;让这么多人蜂拥而至&…

html 去除max-height,HTML Style maxHeight用法及代码示例

maxHeight属性设置/返回元素的最大高度。 maxHeight属性仅影响block-level元素&#xff0c;绝对或固定位置元素。用法:它用于设置maxHeight属性&#xff1a;object.style.maxHeight "none|length|%|initial|inherit"它用于返回maxHeight属性&#xff1a;object.styl…

数据结构——图-有向带权图的邻接表

#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型&#xff08;char&#xff09; #define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表 {int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置int weight; …

ASP.NET Core使用HostingStartup增强启动操作

概念在ASP.NET Core中我们可以使用一种机制来增强启动时的操作&#xff0c;它就是HostingStartup。如何叫"增强"操作&#xff0c;相信了解过AOP概念的同学应该都非常的熟悉。我们常说AOP使用了关注点分离的方式&#xff0c;增强了对现有逻辑的操作。而我们今天要说的…

计算机网络实验arp协议分析,计算机网络ARP地址协议解析实验报告

计算机网络ARP地址协议解析实验报告 (5页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;9.9 积分计算机网络实验报告、实验目的:1. 掌握ARP协议的报文格式2. 掌握ARP协议的工作原理3. 理解ARP高速缓存…

数据结构——图-最短路径长度中最大的一个

#include<stdio.h> #include<string.h> #define INF 32767 #define MAXVEX 30 int dist[MAXVEX]; //建立dist数组int path[MAXVEX]; //建立path数组int S[MAXVEX]; //建立S数组typedef char VertexType;typedef struct graph {int n,e;VertexType vexs[MAXVE…

一个情怀引发的生产事故

在一个项目中&#xff0c;需要轻量级用到脚本语言&#xff0c;来提高应用服务的灵活性。因为知道Roslyn可以动态编辑C#&#xff0c;本着情怀&#xff0c;就自然用Roslyn来处理这块业务了。开在windows上执行&#xff0c;一次调用风平浪静&#xff0c;因为这个功能使用频次不高&…

python standardscaler_教你用python一步步解决“维度灾难”

全文共7016字&#xff0c;预计学习时长40分钟或更长现代科技时代产生和收集的数据越来越多。然而在机器学习中&#xff0c;太多的数据可不是件好事。某种意义上来说&#xff0c;特征或维度越多&#xff0c;越会降低模型的准确性&#xff0c;因为需要对更多的数据进行泛化——这…

c++的输入和输出

1. 输入/输出流的成员函数 put()函数 put函数常用的调用形式&#xff1a; cout.put(char ch); 功能&#xff1a;用于输出一个字符&#xff0c;还可以是ASCII代码&#xff08;或者是ASCII表达式&#xff09; cout.put(65)&#xff1b; get()函数 常用形式为&#xff1a;cin.g…

被 C# 的 ThreadStatic 标记的静态变量,都存放在哪里了?

一&#xff1a;背景 1. 讲故事前几天公号里有一位朋友留言说&#xff0c;你windbg玩的溜&#xff0c;能帮我分析下被 ThreadStatic 修饰的变量到底存放在哪里吗&#xff1f;能不能帮我挖出来????????????&#xff0c;其实这个问题问的挺深的&#xff0c;玩高级语言…

唐山师范学院计算机论文,唐山师范学院校园网络解决方案 毕业论文

唐山师范学院校园网络解决方案 毕业论文 (43页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;9.90 积分1 唐山师范学院 专 科毕业论文 题 目 唐山师范学院校园网络解决方案 学 生 指导教师 年 级 200…

基本系统设备感叹号更新不了_电脑识别不了U盘?别紧张,免费教你如何解决...

你的电脑会出现识别不了U盘的情况吗&#xff1f;为什么会识别不了U盘你了解过吗&#xff1f;首先我们说一下&#xff0c;U盘作为一个办公必备品&#xff0c;用来存储文件以便随时使用&#xff0c;简单方便。但是如果某一天你的电脑突然之间无法识别U盘的话&#xff0c;就代表新…

群同态基本定理证明_群论(7): 群代数, 群表示基础

内容提要:1 群代数; 2 域上的有限维群代数和Maschke定理; 3 函数环; 4 代数闭域上的群表示论; 本文主要参考文献.本文的前置内容为:格罗卜&#xff1a;群论(1): 群, 同构定理, 循环群格罗卜&#xff1a;群论(2): 群作用, Sylow定理更多内容&#xff0c;请移步专栏目录:格罗卜&a…

c++的文件输入/输出

1文件的概述 根据文件中数据的组织形式分为&#xff1a; 1 文本文件 文本文件又称ASCII文件&#xff0c;它的每一个字节存放一个ASCII代码&#xff0c;代表一个字符 输出文本&#xff1a;接收从内存输出的数据 输出文件&#xff0c;向它写入数据 ofstream fout; 输入文件&…

南阳理工计算机全国排名,全国工科实力最强的10所高校排名,

评价工科实力一个非常明显的指标就是学科实力&#xff0c;2017年公布的第四次学科评估结果就是最好的参考。下面就以学科评估排名全国5%的学科数作为评比基准&#xff0c;对国内主要高校的工科实力进行一个排名&#xff0c;结果如下&#xff1a;前3甲&#xff1a;清华大学、浙江…

真正的高手,都有增长思维!(深度好文)

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份职场&认知洞察 丨 作者 / findyi这是findyi公众号分享的第99篇原创文章最近几年互联网红利消亡&#xff0c;老板们非常焦虑。这也一度让所谓的「首席增长官」被媒体热炒。仿佛来一个增长的救世主&#xf…

service层中有某个事物要立马提交_硬货你要的,binder机制来了

欢迎关注专栏&#xff1a;里面定期分享Android和Flutter架构技术知识点及解析&#xff0c;还会不断更新的BATJ面试专题&#xff0c;欢迎大家前来探讨交流&#xff0c;如有好的文章也欢迎投稿。Android高级进阶​zhuanlan.zhihu.com前言Binder做为Android中核心机制&#xff0c;…

学习笔记 | 传统企业互联网改革之道

【学习笔记】| 作者 / Edison Zhou这是EdisonTalk的第306篇学习分享最近在看刘润老师的《互联网战略版&#xff1a;传统企业&#xff0c;互联网在踢门》&#xff0c;学习了传统企业互联网改革的价值模型与三大模式&#xff0c;醍醐灌顶受益良多。因此&#xff0c;我将我学到的总…