高度为5的3阶b树含有的关键字个数_第15期:索引设计(索引组织方式 B+ 树)

4f1f7825242bffb1c907ea66c3842e3b.png

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

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

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

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

一、什么是二叉树?

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

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

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

7d107bbe29e60a3ee23690673168cd83.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 的儿子节点,这棵树就退化为一张链表。

06dc73779c6fbe2220ad9faae2c8383f.png

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

二、平衡二叉树(AVL)

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

5dd228a0de58e4ccbb445a248882a430.png

图 2 可以看到以下特性:

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

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:

31d5ab1d752facea220f9196a3056a14.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:

dd9a88b0acc79c950a28b7e3f4633ede.png

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

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

eee25f7f500b9d5ceb953b546add8966.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:

330eead27fb77e04ab36d1788c9586f7.png

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

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


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

d1b95d1cb3b30e6666c44c1ff23427b9.png

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

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

相关文章

ARMS企业级场景被集成场景介绍

简介&#xff1a; ARMS企业级场景被集成场景介绍 通过本次最佳实践内容&#xff0c;您可以看到ARMS OpenAPI可以灵活的被集成到客户链路监控场景&#xff0c;并对其进行可视化图形展示监控信息。 1. 背景信息 应用实时监控服务ARMS&#xff08;Application Real-Time Monitor…

千万并发连接下,如何保障网络性能

过去几十年互联网呈爆发式的增长&#xff0c;内容的丰富以及层出不穷的DDoS攻击等&#xff0c;对网络性能提出了极大的挑战&#xff0c;也同样促进了网络基础设施的快速发展。运营商的带宽越来越大&#xff0c;CPU/网卡等硬件的性能也会越来越强。但在很长时间内&#xff0c;软…

kafka window 启动_Apache Flink结合Kafka构建端到端的Exactly-Once处理

Apache Flink自2017年12月发布的1.4.0版本开始&#xff0c;为流计算引入了一个重要的里程碑特性&#xff1a;TwoPhaseCommitSinkFunction&#xff08;相关的Jira&#xff09;。它提取了两阶段提交协议的通用逻辑&#xff0c;使得通过Flink来构建端到端的Exactly-Once程序成为可…

浅谈云原生架构的 7 个原则

简介&#xff1a; 作为一种架构模式&#xff0c;云原生架构通过若干原则来对应用架构进行核心控制。这些原则可以帮助技术主管和架构师在进行技术选型时更加高效、准确&#xff0c;下面将展开具体介绍。 服务化原则 在软件开发过程中&#xff0c;当代码数量与开发团队规模都扩…

深入浅出FlatBuffers原理

简介&#xff1a; FlatBuffers 是一个开源的、跨平台的、高效的、提供了多种语言接口的序列化工具库。实现了与 Protocal Buffers 类似的序列化格式。主要由 Wouter van Oortmerssen 编写&#xff0c;并由 Google 开源。本文将基于高德地图数据编译增量发布使用了FlatBuffers序…

java 反编译class文件_用Java实现JVM第三章《解析class文件》

解析class文件案例介绍本案例主要介绍通过java代码从class文件中解析&#xff1b;class文件、常量池、属性表&#xff1b;作为类(或者接口)信息的载体&#xff0c;每个class文件都完整地定义了一个类。为了使java程序可以“编写一次&#xff0c;处处运行”&#xff0c;Java虚拟…

解放人与设备距离,5G时代的远程操控该如何完成

物联网这个概念早在十多年前便已提出&#xff0c;其主要依托于移动通讯网络来实现其功能的传输。在过去物联网领域的一些设备控制场景中&#xff0c;我们或多或少都见到过远程控制技术的身影&#xff0c;但受限于当时的网络条件和技术场景&#xff0c;大部分应用都属于对设备的…

Spark 大数据处理最佳实践

开源大数据社区 & 阿里云 EMR 系列直播 第十一期 主题&#xff1a;Spark 大数据处理最佳实践 讲师&#xff1a;简锋&#xff0c;阿里云 EMR 数据开发平台 负责人 内容框架&#xff1a; 大数据概览如何摆脱技术小白Spark SQL 学习框架EMR Studio 上的大数据最佳实践 直播…

CNCF TOC 委员张磊:不断演进的云原生给我们带来了什么?

简介&#xff1a; 任何一种云原生技术&#xff0c;它不再是某种能力的弥补&#xff0c;而是更多地将云的能力以某种方式更简单、更高效地透出给我的应用去使用。无论是容器、K8s 还是 Service Mesh&#xff0c;他们都是在不同的环节帮助应用本身能够更好地去使用云服务。 作者…

php url传递参数_互联网系统(APP、网站等)通信基石——会话(PHP版)

一、会话概述1.1、技术背景互联网通信中采用的Http协议(建立TCP连接->Http请求->Http应答->断开TCP连接)本身是无状态的&#xff0c;即Http各请求之间是相互独立、互不相关的&#xff0c;而大量应用需要将各请求关联起来(如&#xff1a;用户登录系统购物、多次购买行为…

十年探索,云上明灯,re:Invent再启掀产业风暴

15年前&#xff0c;IT基础设施有着太多的限制&#xff0c;成本高、反应慢、灵活度低&#xff0c;对于企业的创新与发展有着很大的伤害。当亚马逊推出全球第一个云计算服务简单存储 Amazon S3时&#xff0c;可能没有太多人相信&#xff0c;这些内容将会开启一个新世界的大门&…

用手机「3D探店」是种什么体验?

简介&#xff1a; 未来场景尽在眼前&#xff01;阿里云3D全景网站通过云端算法技术自动建模&#xff0c;将线下场景1:1真实还原到线上&#xff0c;让用户足不出户就可以感受到真实的3D空间漫游效果。 在手机里用3D探店打卡是种什么样的体验&#xff1f; 走进商场&#xff0c;每…

mysql bin oct_python 讲解进制转换 int、bin、oct、hex

相关免费学习推荐&#xff1a;python视频教程原理十进制转n进制都可以使用倒除法&#xff1a;对十进制进行除n的运算&#xff0c;直到商为0为止&#xff0c;然后将各个步骤中得到的余数倒着写出来.n进制转十进制&#xff1a;(例子&#xff1a;二进制转十进制)101001 > 2^5 …

java设置字体大小和颜色_Java 设置Excel图表背景填充(颜色、图片填充)

本文介绍通过Java程序来设置Excel图表背景填充的方法&#xff0c;填充时&#xff0c;可设置颜色填充或者加载图片填充&#xff1b;填充区域可设置整个图表区域或者绘图区域。设置方法参考以下内容。使用工具&#xff1a;Free Spire.XLS for Java&#xff08;免费版&#xff09;…

英特尔TCI技术落地,锐捷网络发布OCS终端云化新品

编辑 | 宋慧 出品 | CSDN 云计算 2021 年 6 月&#xff0c;国内一直深耕桌面虚拟化的厂商锐捷正式发布了新一代云桌面解决方案——锐捷三擎云桌面解决方案&#xff08; “精耕细作”桌面云市场的锐捷&#xff0c;重磅发布三擎云桌面 &#xff09;&#xff0c;其中三擎指的是终端…

从理念到实践跳跃式演进! 云的原生“免疫系统”如何有机作战?

简介&#xff1a; 7月16日&#xff0c;以“原生安全二倍速&#xff1a;全面融入基础设施”为主题的阿里云原生安全线上专题活动收官&#xff0c;诠释由云而生的能力如何解决数字经济时代的安全新挑战&#xff0c;让高等级安全作为一种基础设施&#xff0c;成为数字业务发展的“…

安卓开发替换json字符串中的数据_22个JavaScript开发技巧合集

作者&#xff1a;kancloud转发链接&#xff1a;https://www.kancloud.cn/dennis/tgjavascript/241855开发技巧1、使用var声明变量如果给一个没有声明的变量赋值&#xff0c;默认会作为一个全局变量(即使在函数内赋值)。要尽量避免不必要的全局变量。2、行尾使用分号虽然JavaScr…

Python静态类型解析工具简介和实践

简介&#xff1a; Python是一门强类型的动态类型语言&#xff0c;开发者可以给对象动态指定类型&#xff0c;但类型不匹配的操作是不被允许的。动态类型帮助开发者写代码轻松愉快&#xff0c;然而&#xff0c;俗话说&#xff1a;动态一时爽&#xff0c;重构火葬场。动态类型也带…

拥抱创新二十载,微软“创新杯”持续孵化中国青年开发者智慧创意

12月13日&#xff0c;2022 第二十届微软“创新杯”全球学生大赛&#xff08;以下简称“创新杯”&#xff09;中国区总决赛结果正式揭晓。来自西安的 Silent Talk 团队凭借Silent Talk—— Speech Rehabilitation Training 项目&#xff0c;在 22 支决赛队伍中脱颖而出&#xff…

AI和大数据结合,智能运维平台助力流利说提升核心竞争力

简介&#xff1a; 简介&#xff1a;本文整理自数智创新行——智能运维专场&#xff08;上海站&#xff09;&#xff0c;流利说最佳实践演讲&#xff1a;《基于SLS千万级在线教育平台统一监控运营实践》 作者&#xff1a; 孙文杰 流利说运维总监 元乙 阿里云智能技术专家 优质…