mysql b 树原因_复习系列之数据库(四):MySQL为什么采用B+树作为索引结构?

MySQL中数据是索引组织表,即表中数据按照主键顺序存放。所以就可以基于索引这种数据结构实现一些高级算法,来提高检索效率。

常见的查找算法

顺序查找:复杂度O(n),在数据量大时,效率很低

二分查找:在有序为前提,复杂度O(logn)

hash查找:无法满足范围查找

二叉树查找:O(logn),每个节点只能有一个左节点和一个右节点

试着用二叉树来构造一种索引方式

为什么MySQL没有采用二叉树来构造索引呢?

由磁盘的物理结构决定的。

首先,二叉树中每个节点只能有一个左节点和一个右节点,直接导致树的高度很高,逻辑上相近的节点,无法利用局部性,相邻节点没法直接通过指针相连,可能需要返回上层节点重复递归找到结果,效率低。

其次,当数据量大时,内存不够,大部分数据只能存放在磁盘上,只有在需要的时候才加载到内存中,但是磁盘读取速度显然与内存差很多,大部分时间会阻塞在IO上面,为了减少磁盘IO次数,上面这些传统的树无法满足。

磁盘结构

下面是磁盘整体结构示意图

868ab68892b6b69fc07b11a7e059888e.png

其中,磁盘可以转动(各个磁盘必须同步转动)。每个磁头负责存取一个磁盘的内容。磁头不能转动,但是可以沿磁盘半径方向运动(实际是斜切向运动)。

盘片结构示意图

c802823782e9f72dbde11bb1bfd79e1b.png

盘片被划分成一系列同心环,圆心是盘片中心,每个同心环叫做一个磁道,所有半径相同的磁道组成一个柱面。

磁道被沿半径线划分成一个个小的段,每个段叫做一个扇区,每个扇区是磁盘的最小存储单元。

磁盘如何读取数据?

磁盘如何可以提高IO效率?

为了提高效率,要尽量减少磁盘I/O,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

预读的长度一般为页(page)(在许多操作系统中,页的大小通常为4k)的整倍数。主存和磁盘以页为单位交换数据。

当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

为了减少磁盘 IO 次数,B-/B+树应运而生。

B-/B+树

B-树

为了更快,B-树每次将范围分割为多个区间,区间越多,定位数据越快越精确。

所以新建节点时,直接申请页大小的空间,计算机内存分配是按页对齐的,这样就实现了一个节点只需要一次 IO。那么总 IO 的次数就缩减为了 log n 次。

下面是一棵简化的B-树:

9e63ae6bd160920cc05ed56e55e80635.png

B-树的每个节点是 n 个有序的序列(a1,a2,a3…an),并将该节点的子节点分割成 n+1 个区间来进行索引(X1< a1, a2 < X2 < a3, … , an+1 < Xn < anXn+1 > an)。每个 key 值紧跟着 data 域,B-树的 key 和 data 是聚合在一起的。

B-树的如何进行查找的?

比如上图中,若搜索 key 为 25 节点的 data,首先在根节点进行二分查找(因为 keys 有序,二分最快),判断 key 25 小于 key 50,所以定位到最左侧的节点,此时进行一次磁盘 IO,将该节点从磁盘读入内存,接着继续进行上述过程,直到找到该 key 为止。

B+树

B+树是B-树的变种,它与B-树的不同之处在于:

在B+树中,key 副本存储在内部节点,真正的 key 和 data 存储在叶子节点上 。

n 个 key 值的节点指针域为 n 而不是 n+1。

为了增加 区间访问性,一般会对B+树做一些优化,增加了顺序访问指针。

下面是一棵简化的B+树:

b937d04ccf2e3aeec41f9edb5a45280c.png

因为内节点并不存储 data,所以一般B+树的叶节点和内节点大小不同,而B-树的每个节点大小一般是相同的,为一页。

因为增加了顺序访问指针,图中如果要查询key为从55到62的所有数据记录,当找到50后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

B-树与B+树区别

1.B+树内节点不存储数据,所有 data 存储在叶节点导致查询时间复杂度固定为 log n。而B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)。

如上图,如果查找50,刚好第一次就可以查找出来,所以最好情况是O(1)。由于B+树所有的 data 域都在根节点,所以查询 key 为 50的节点必须从根节点索引到叶节点,时间复杂度固定为 O(log n)。

2.B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等,而B-树每个节点 key 和 data 在一起,则无法区间查找。

B+树可以很好的利用局部性原理,若我们访问节点 key为 50,则 key 为 55、60、62 的节点将来也可能被访问,我们可以利用磁盘预读原理提前将这些数据读入内存,减少了磁盘 IO 的次数。当然B+树也能够很好的完成范围查询。比如查询 key 值在 50-70 之间的节点。

3.B+树更适合外部存储。由于内节点无 data 域,每个节点能索引的范围更大更精确

由于B-树节点内部每个 key 都带着 data 域,而B+树节点只存储 key 的副本,真实的 key 和 data 域都在叶子节点存储。由于磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大。这就意味着B+树单次磁盘 IO 的信息量大于B-树,从这点来看B+树相对B-树磁盘 IO 次数少。

MySQL索引实现

在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。

索引分为:

聚集索引(Primary key):按照每张表的主键构造一棵B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚集索引的叶子节点称为数据页。每个数据页都通过一个双向链表来进行链接。每张表只能拥有一个聚集索引。

辅助索引(Secondary key):叶子节点并不包含行记录的全部数据。叶子节点除了包含键值以外,还包含一个书签,该书签找到与索引相对应的行数据。每张表可以有多个辅助索引。

MyISAM引擎的实现

下图是MyISAM索引的原理图:

5ca5043ff875319d445a1b992a2b0e23.png

在MyISAM中,主索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:

44079bb873a56bd11f3702d5b9c69634.png

InnoDB引擎的实现

而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。

这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

下图是InnoDB主索引示意图:

34ce67d8e5b5d849ba20a466b8f7a583.png

可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)。

下图为定义在Col3上的一个辅助索引:

f0372f540800189b1bc3bf819c16c60c.png

这里以英文字符的ASCII码作为比较准则。辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

这里就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。

非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

数据的查找

1、精确查找: select * from user_info where id = 23

内存中找到根节点,根节点二分查找确定范围,逐层向下查找,读取叶子节点,通过二分查找找到记录或未命中。

d97129938c8e6317271ba74afb3460c7.png

2、索引范围查找:select * from user_info where id >= 18 and id < 22

内存中找到根节点,确定索引定位条件id=18,找到满足条件第一个叶节点

,顺序扫描所有结果,直到终止条件满足id >=22

2ada3f43f486e9183ac04d04f40dcb4c.png

3、全表扫描:select * from user_info where name = 'abc'

直接读取叶节点头结点, 顺序扫描, 返回符合条件记录, 到最终节点结束

4、二级索引查找:Select * from table_x where name = “d”;

id是主索引,name是二级索引。

通过二级索引查出对应主键,拿主键回表查主键索引得到数据, 二级索引可筛选掉大量无效记录,提高效率。

参考文献:1、《MySQL技术内幕》

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

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

相关文章

windows无法检索有关这台计算机上的磁盘信息_磁盘镜像软件OO DiskImage Pro 15.5介绍及安装教程...

Active Disk Image是一种磁盘映像软件&#xff0c;可以精确复制任何PC磁盘(HDD&#xff0c;SSD&#xff0c;USB&#xff0c;CD&#xff0c;DVD&#xff0c;Blu-ray等)并将其存储在文件夹中。磁盘映像可用于备份&#xff0c;PC升级或磁盘复制。万一计算机出现故障&#xff0c;可…

word手写字体以假乱真_Word小技巧|打印作文草稿纸

前期介绍过一些Word使用中的小技巧&#xff0c;例如WORD快速查找的2个小技巧 https://www.iappi.cn/2019_08/20191147.html&#xff0c;使用Word创建九宫格图像 https://www.iappi.cn/2019_07/20191064.html 等。今天再分享一个打印作文草稿纸的技巧。很多时候需要规范写好作文…

概要设计说明书_没有什么比牙签更好的设计了

牙签是设计公理的典型例子&#xff0c;形式服从功能。它的形式和功能是单一的、紧凑的、轻质的、可生物降解的、可持续的实体。不证自明的&#xff1a;它的形状是设计功能的缩影&#xff0c;同时作为手柄和说明书。它的形状不仅告诉你如何握住和使用它&#xff0c;而且告诉你把…

java项目log4j_java项目测试log4j

一、基础入门1.1 下载安装下载相应的log4j-1.2.15.jar(也可以下载其他的版本)提供一个下载jar包的网站(http://search.maven.org/)新建一个log4j.properties文件&#xff1a;#配置根Loggerlog4j.rootLoggerinfo, RF #info代表的是日志输出的级别log4j.appender.RForg.apache.lo…

webrtc 代码_英特尔开源WebRTC开发套件OWT

为了抢占实时视频的巨大市场&#xff0c;英特尔开源了WebRTC开发套件&#xff0c;并将其命名为Open WebRTC Toolkit (OWT)。由于实时视频编码、转码需要大量的计算资源&#xff0c;Open WebRTC Toolkit将为英特尔带来巨大的潜在商业回报。文 / Ant去年在旧金山举办的2018 Krank…

零基础自学java_零基础学Java——小白的Java之路(4)

方法方法是一段可以重复调用的代码块&#xff0c;这个代码块实现了某个功能&#xff0c;当我们的程序中需要这一个功能的时候&#xff0c;调用这个方法即可&#xff0c;不再需要重复书写这个功能的代码。方法的定义格式public static ( ,... ){方法体&#xff1b;[return 表达值…

异步fifo_跨时钟域同步(异步FIFO)

本文使用 Zhihu On VSCode 创作并发布跨时钟域同步&#xff08;异步FIFO&#xff09;之前学习了跨时钟域下的单bit信号同步的方法&#xff0c;这些单bit信号多是作为控制信号或者标志信号来使用&#xff0c;再实际的项目中&#xff0c;处理多bit数据也是十分常见的&#xff0c;…

dumpbin发现没有入口函数_JavaScript基础之入口函数-2020版

JavaScript基础之入口函数-2020版1.入口函数window.onload function(){ 内部放js}这个函数的意思就是说&#xff0c;当我们页面加载完毕之后(就是说等页面的结构 样式 节点等加载完毕)&#xff0c;采取执行函数体里面的js部分。也就是说可以使用此方法&#xff0c;就不用考…

农委系统先进集体推荐报告_来自司法行政的他们,荣获上海档案系统表彰!

为表彰先进、弘扬正气&#xff0c;激发全市各级档案部门和广大档案工作者的积极性和创造性&#xff0c;进一步推进上海档案事业创新发展&#xff0c;经各地区、各部门、各单位民主推荐&#xff0c;市人力资源社会保障局和市档案局审核同意&#xff0c;决定授予50家集体“上海市…

java如何获得wlan mac_Android M 如何获取 Wifi MAC地址

今天在撸代码时发现&#xff0c;之前能获取mac地址的方法在nexus 6上返回了“02:00:00:00:00:00”&#xff0c;进入设置查看mac地址&#xff0c;结果不相同&#xff0c;肯定有问题&#xff0c;于是就开始上网查资料一探究竟。原先获取mac地址的代码段&#xff1a;6.0之前获取ma…

我的世界java多大内存_我的世界电脑版内存多大

下载方法如下&#xff1a;1&#xff0c;百度搜索 我的世界电脑版&#xff0c;即可找到下载。2&#xff0c;直接点击普通下载&#xff0c;即可下载。3&#xff0c;我的世界电脑版硬件要求如下&#xff1a;最低配置&#xff1a;CPU&#xff1a;1.5G GHz多和处理器/2.0GHz单核处理…

天正双击墙体不能编辑_今日设计分享:CAD常用快捷键、Ps快捷键大全、天正快捷键总结!...

▶今天记忆一个技巧&#xff0c;成就明天一个大师&#xff01;▶同行小可爱们&#xff0c;加油吧&#xff01;CAD最常用快捷键L直线&#xff1b;PL多段线&#xff1b;U回车Ctrlz后退&#xff1b;D修改&#xff0c;调整&#xff1b;REC矩形&#xff1b;C圆&#xff1b;TR修剪&am…

odoo tree视图过滤数据_数据存储结构 LSM Tree PK B TREE (从底层了解数据库设计)...

随着使用数据库的深度和理解能力的提升&#xff0c;有一个问题硬件的提升,与数据量的变化是否对数据库底层的架构有冲击。 我们公认的BTREE BTREE 是否还能面对现在的硬件的变化。 BTREE 到底是为那种硬件逻辑来服务的&#xff0c;这点是需要搞清楚的在MYSQL 中使用的BTREE的改…

java rpm包安装_rpm包安装java jar开机自启

1.下载jdk2.安装jdk&#xff1b;rpm -ivh jdk-8u201-linux-x64.rpm3.检查安装&#xff1a;java -version输出Java版本&#xff0c;则不用第4步和第5步4.配置jdk路径打开/etc/profile增加以下内容&#xff1a;export JAVA_HOME/usr/java/jdk1.8.0_201export JAVA_BIN/usr/java/j…

java电脑类的接口_java 一个类实现两个接口的案例

直接用英文逗号分隔就可以了&#xff0c;比如&#xff1a;?12345678910111213141516171819inerface IHello {String sayHello(String name);}interface IHi {String sayHi(String name);}class ServiceImplimplements IHello, IHi {// 实现三个四个。。。n个接口都是使用逗号分…

基于java二手书论文_java毕业设计_springboot框架的二手书交易管理与实现

今天介绍一个java毕设题目, 题目内容为springboot框架的二手书交易管理与实现, 是一个采用b/s结构的javaweb项目, 采用java语言编写开发工具eclipse, 项目框架jspspringbootmybatis, 二手书交易管理与实现的信息存储于mysql中, 并基于mybatis进行了orm封装, 该二手书交易管理与…

java怎么给list集合排序_java list集合排序按某一属性排序操作

我就废话不多说了&#xff0c;大家还是直接看代码吧~public List sortList(List list){Collections.sort(list, new Comparator(){Overridepublic int compare(FreightM o1, FreightM o2) {if(o1.getType()0){return -1;}else{return 1;}}});return list;}实现compareTo()方法&…

java字符流实际上也是字节,[Java教程]Java字节流与字符流的区别

[Java教程]Java字节流与字符流的区别0 2017-05-22 12:00:42字节流与和字符流的使用非常相似&#xff0c;两者除了操作代码上的不同之外&#xff0c;是否还有其他的不同呢&#xff1f;实际上字节流在操作时本身不会用到缓冲区(内存)&#xff0c;是文件本身直接操作的&#xff0c…

php获取html中文本框内容_小猿圈Python入门之批量获取html内body内容的方法

对于人工智能你了解有多少&#xff1f;你知道Python的使用吗&#xff1f;这个对于大部分初学者来说都是很难的&#xff0c;小猿圈Python讲师会每天为大家选择分享一个知识点&#xff0c;希望对你学习Python有所帮助&#xff0c;今天分享的就是批量获取html内body内容的方法。现…

php改名下载,PHP如何给上传的文件改名

PHP如何给上传的文件改名发布时间&#xff1a;2020-08-03 16:07:39来源&#xff1a;亿速云阅读&#xff1a;72作者&#xff1a;LeahPHP如何给上传的文件改名&#xff1f;相信很多没有经验的人对此束手无策&#xff0c;为此本文总结了问题出现的原因和解决方法&#xff0c;通过这…