范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

女朋友问我为什么MySQL喜欢B树?我笑着画了20张图

  大家好,我是小林。
  「为什么 MySQL 采用 B+ 树作为索引?」这句话,是不是在面试时经常出现。
  要解释这个问题,其实不单单要从数据结构的角度出发,还要考虑磁盘 I/O 操作次数,因为 MySQL 的数据是存储在磁盘中的嘛。
  这次,就跟大家一层一层的分析这个问题,图中包含大量的动图来帮助大家理解,相信看完你就拿捏这道题目了!
  怎样的索引的数据结构是好的?
  MySQL 的数据是持久化的,意味着数据(索引+记录)是保存到磁盘上的,因为这样即使设备断电了,数据也不会丢失。
  磁盘是一个慢的离谱的存储设备,有多离谱呢?
  人家内存的访问速度是纳秒级别的,而磁盘访问的速度是毫秒级别的,也就是说读取同样大小的数据,磁盘中读取的速度比从内存中读取的速度要慢上万倍,甚至几十万倍。
  磁盘读写的最小单位是扇区 ,扇区的大小只有 512B   大小,操作系统一次会读写多个扇区,所以操作系统的最小读写单位是块(Block)。Linux 中的块大小为 4KB  ,也就是一次磁盘 I/O 操作会直接读写 8 个扇区。
  由于数据库的索引是保存到磁盘上的,因此当我们通过索引查找某行数据的时候,就需要先从磁盘读取索引到内存,再通过索引从磁盘中找到某行数据,然后读入到内存,也就是说查询过程中会发生多次磁盘 I/O,而磁盘 I/O 次数越多,所消耗的时间也就越大。
  所以,我们希望索引的数据结构能在尽可能少的磁盘的 I/O 操作中完成查询工作,因为磁盘 I/O 操作越少,所消耗的时间也就越小。
  另外,MySQL 是支持范围查找的,所以索引的数据结构不仅要能高效地查询某一个记录,而且也要能高效地执行范围查找。
  所以,要设计一个适合 MySQL 索引的数据结构,至少满足以下要求: 能在尽可能少的磁盘的 I/O 操作中完成查询工作; 要能高效地查询某一个记录,也要能高效地执行范围查找;
  分析完要求后,我们针对每一个数据结构分析一下。  什么是二分查找?
  索引数据最好能按顺序排列,这样可以使用「二分查找法」高效定位数据。
  假设我们现在用数组来存储索引,比如下面有一个排序的数组,如果要从中找出数字 3,最简单办法就是从头依次遍历查询,这种方法的时间复杂度是 O(n),查询效率并不高。因为该数组是有序的,所以我们可以采用二分查找法,比如下面这张采用二分法的查询过程图:
  可以看到,二分查找法每次都把查询的范围减半,这样时间复杂度就降到了 O(logn),但是每次查找都需要不断计算中间位置。 什么是二分查找树?
  用数组来实现线性排序的数据虽然简单好用,但是插入新元素的时候性能太低。
  因为插入一个元素,需要将这个元素之后的所有元素后移一位,如果这个操作发生在磁盘中呢?这必然是灾难性的。因为磁盘的速度比内存慢几十万倍,所以我们不能用一种线性结构将磁盘排序。
  其次,有序的数组在使用二分查找的时候,每次查找都要不断计算中间的位置。
  那我们能不能设计一个非线形且天然适合二分查找的数据结构呢?
  有的,请看下图这个神奇的操作,找到所有二分查找中用到的所有中间节点,把他们用指针连起来,并将最中间的节点作为根节点。
  怎么样?是不是变成了二叉树,不过它不是普通的二叉树,它是一个二叉查找树 。
  二叉查找树的特点是一个节点的左子树的所有节点都小于这个节点,右子树的所有节点都大于这个节点 ,这样我们在查询数据时,不需要计算中间节点的位置了,只需将查找的数据与节点的数据进行比较。
  假设,我们查找索引值为 key 的节点: 如果 key 大于根节点,则在右子树中进行查找; 如果 key 小于根节点,则在左子树中进行查找; 如果 key 等于根节点,也就是找到了这个节点,返回根节点即可。
  二叉查找树查找某个节点的动图演示如下,比如要查找节点 3 :
  另外,二叉查找树解决了插入新节点的问题,因为二叉查找树是一个跳跃结构,不必连续排列。这样在插入的时候,新节点可以放在任何位置,不会像线性结构那样插入一个元素,所有元素都需要向后排列。
  下面是二叉查找树插入某个节点的动图演示:
  因此,二叉查找树解决了连续结构插入新元素开销很大的问题,同时又保持着天然的二分结构。
  那是不是二叉查找树就可以作为索引的数据结构了呢?
  不行不行,二叉查找树存在一个极端情况,会导致它变成一个瘸子!
  当每次插入的元素都是二叉查找树中最大的元素,二叉查找树就会退化成了一条链表,查找数据的时间复杂度变成了 O(n) ,如下动图演示:
  由于树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作( 假设一个节点的大小「小于」操作系统的最小读写单位块的大小  ),也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数 ,所以树的高度越高,就会影响查询性能。
  二叉查找树由于存在退化成链表的可能性,会使得查询操作的时间复杂度从 O(logn)降低为 O(n)。
  而且会随着插入的元素越多,树的高度也变高,意味着需要磁盘 IO 操作的次数就越多,这样导致查询性能严重下降,再加上不能范围查询,所以不适合作为数据库的索引结构。 什么是自平衡二叉树?
  为了解决二叉查找树会在极端情况下退化成链表的问题,后面就有人提出平衡二叉查找树(AVL 树) 。
  主要是在二叉查找树的基础上增加了一些条件约束:每个节点的左子树和右子树的高度差不能超过 1 。也就是说节点的左子树和右子树仍然为平衡二叉树,这样查询操作的时间复杂度就会一直维持在 O(logn) 。
  下图是每次插入的元素都是平衡二叉查找树中最大的元素,可以看到,它会维持自平衡:
  除了平衡二叉查找树,还有很多自平衡的二叉树,比如红黑树,它也是通过一些约束条件来达到自平衡,不过红黑树的约束条件比较复杂,不是本篇的重点重点,大家可以看《数据结构》相关的书籍来了解红黑树的约束条件。
  下面是红黑树插入节点的过程,这左旋右旋的操作,就是为了自平衡。
  不管平衡二叉查找树还是红黑树,都会随着插入的元素增多,而导致树的高度变高,这就意味着磁盘 I/O 操作次数多,会影响整体数据查询的效率 。
  比如,下面这个平衡二叉查找树的高度为 5,那么在访问最底部的节点时,就需要磁盘 5 次 I/O 操作。
  根本原因是因为它们都是二叉树,也就是每个节点只能保存 2 个子节点 ,如果我们把二叉树改成 M 叉树(M>2)呢?
  比如,当 M=3 时,在同样的节点个数情况下,三叉树比二叉树的树高要矮。
  因此,当树的节点越多的时候,并且树的分叉数 M 越大的时候,M 叉树的高度会远小于二叉树的高度 。 什么是 B 树
  自平衡二叉树虽然能保持查询操作的时间复杂度在O(logn),但是因为它本质上是一个二叉树,每个节点只能有 2 个子节点,那么当节点个数越多的时候,树的高度也会相应变高,这样就会增加磁盘的 I/O 次数,从而影响数据查询的效率。
  为了解决降低树的高度的问题,后面就出来了 B 树,它不再限制一个节点就只能有 2 个子节点,而是允许 M 个子节点 (M>2),从而降低树的高度。
  B 树的每一个节点最多可以包括 M 个子节点,M 称为 B 树的阶,所以 B 树就是一个多叉树。
  假设 M = 3,那么就是一棵 3 阶的 B 树,特点就是每个节点最多有 2 个(M-1个)数据和最多有 3 个(M个)子节点,超过这些要求的话,就会分裂节点,比如下面的的动图:
  我们来看看一棵 3 阶的 B 树的查询过程是怎样的?
  假设我们在上图一棵 3 阶的 B 树中要查找的索引值是 9 的记录那么步骤可以分为以下几步: 与根节点的索引(4,8)进行比较,9 大于 8,那么往右边的子节点走; 然后该子节点的索引为(10,12),因为 9 小于 10,所以会往该节点的左边子节点走; 走到索引为9的节点,然后我们找到了索引值 9 的节点。
  可以看到,一棵 3 阶的 B 树在查询叶子节点中的数据时,由于树的高度是 3 ,所以在查询过程中会发生 3 次磁盘 I/O 操作。
  而如果同样的节点数量在平衡二叉树的场景下,树的高度就会很高,意味着磁盘 I/O 操作会更多。所以,B 树在数据查询中比平衡二叉树效率要高。
  但是 B 树的每个节点都包含数据(索引+记录),而用户的记录数据的大小很有可能远远超过了索引数据,这就需要花费更多的磁盘 I/O 操作次数来读到「有用的索引数据」。
  而且,在我们查询位于底层的某个节点(比如 A 记录)过程中,「非 A 记录节点」里的记录数据会从磁盘加载到内存,但是这些记录数据是没用的,我们只是想读取这些节点的索引数据来做比较查询,而「非 A 记录节点」里的记录数据对我们是没用的,这样不仅增多磁盘 I/O 操作次数,也占用内存资源。
  另外,如果使用 B 树来做范围查询的话,需要使用中序遍历,这会涉及多个节点的磁盘 I/O 问题,从而导致整体速度下降。 什么是 B+ 树?
  B+ 树就是对 B 树做了一个升级,MySQL 中索引的数据结构就是采用了 B+ 树,B+ 树结构如下图:
  B+ 树与 B 树差异的点,主要是以下这几点: 叶子节点(最底部的节点)才会存放实际数据(索引+记录),非叶子节点只会存放索引; 所有索引都会在叶子节点出现,叶子节点之间构成一个有序链表; 非叶子节点的索引也会同时存在在子节点中,并且是在子节点中所有索引的最大(或最小)。 非叶子节点中有多少个子节点,就有多少个索引;
  下面通过三个方面,比较下 B+ 和 B 树的性能区别。 1、单点查询
  B 树进行单个索引查询时,最快可以在 O(1) 的时间代价内就查到,而从平均时间代价来看,会比 B+ 树稍快一些。
  但是 B 树的查询波动会比较大,因为每个节点即存索引又存记录,所以有时候访问到了非叶子节点就可以找到索引,而有时需要访问到叶子节点才能找到索引。
  B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少 。 2、插入和删除效率
  B+ 树有大量的冗余节点,这样使得删除一个节点的时候,可以直接从叶子节点中删除,甚至可以不动非叶子节点,这样删除非常快,
  比如下面这个动图是删除 B+ 树某个叶子节点节点的过程:
  注意,:B+ 树对于非叶子节点的子节点和索引的个数,定义方式可能会有不同,有的是说非叶子节点的子节点的个数为 M 阶,而索引的个数为 M-1(这个是维基百科里的定义),因此我本文关于 B+ 树的动图都是基于这个。但是我在前面介绍 B+ 树与 B+ 树的差异时,说的是「非叶子节点中有多少个子节点,就有多少个索引」,主要是 MySQL 用到的 B+ 树就是这个特性。
  甚至,B+ 树在删除根节点的时候,由于存在冗余的节点,所以不会发生复杂的树的变形,比如下面这个动图是删除 B+ 树根节点的过程:
  B 树则不同,B 树没有冗余节点,删除节点的时候非常复杂,比如删除根节点中的数据,可能涉及复杂的树的变形,比如下面这个动图是删除 B 树根节点的过程:
  B+ 树的插入也是一样,有冗余节点,插入可能存在节点的分裂(如果节点饱和),但是最多只涉及树的一条路径。而且 B+ 树会自动平衡,不需要像更多复杂的算法,类似红黑树的旋转操作等。
  因此,B+ 树的插入和删除效率更高 。 3、范围查询
  B 树和 B+ 树等值查询原理基本一致,先从根节点查找,然后对比目标数据的范围,最后递归的进入子节点查找。
  因为 B+ 树所有叶子节点间还有一个链表进行连接,这种设计对范围查找非常有帮助 ,比如说我们想知道 12 月 1 日和 12 月 12 日之间的订单,这个时候可以先查找到 12 月 1 日所在的叶子节点,然后利用链表向右遍历,直到找到 12 月12 日的节点,这样就不需要从根节点查询了,进一步节省查询需要的时间。
  而 B 树没有将所有叶子节点用链表串联起来的结构,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。
  因此,存在大量范围检索的场景,适合使用 B+树,比如数据库。而对于大量的单个索引查询的场景,可以考虑 B 树,比如 nosql 的MongoDB。 MySQL 中的 B+ 树
  MySQL 的存储方式根据存储引擎的不同而不同,我们最常用的就是 Innodb 存储引擎,它就是采用了 B+ 树作为了索引的数据结构。
  下图就是 Innodb 里的 B+ 树:
  但是 Innodb 使用的 B+ 树有一些特别的点,比如: B+ 树的叶子节点之间是用「双向链表」进行连接,这样的好处是既能向右遍历,也能向左遍历。 B+ 树点节点内容是数据页,数据页里存放了用户的记录以及各种信息,每个数据页默认大小是 16 KB。
  Innodb 根据索引类型不同,分为聚集和二级索引。他们区别在于,聚集索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚集索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据。
  因为表的数据都是存放在聚集索引的叶子节点里,所以 InnoDB 存储引擎一定会为表创建一个聚集索引,且由于数据在物理上只会保存一份,所以聚簇索引只能有一个,而二级索引可以创建多个。
  更多关于 Innodb 的 B+ 树,可以看我之前写的这篇:从数据页的角度看 B+ 树。 总结
  MySQL 是会将数据持久化在硬盘,而存储功能是由 MySQL 存储引擎实现的,所以讨论 MySQL 使用哪种数据结构作为索引,实际上是在讨论存储引使用哪种数据结构作为索引,InnoDB 是 MySQL 默认的存储引擎,它就是采用了 B+ 树作为索引的数据结构。
  要设计一个 MySQL 的索引数据结构,不仅仅考虑数据结构增删改的时间复杂度,更重要的是要考虑磁盘 I/0 的操作次数。因为索引和记录都是存放在硬盘,硬盘是一个非常慢的存储设备,我们在查询数据的时候,最好能在尽可能少的磁盘 I/0 的操作次数内完成。
  二分查找树虽然是一个天然的二分结构,能很好的利用二分查找快速定位数据,但是它存在一种极端的情况,每当插入的元素都是树内最大的元素,就会导致二分查找树退化成一个链表,此时查询复杂度就会从 O(logn)降低为 O(n)。
  为了解决二分查找树退化成链表的问题,就出现了自平衡二叉树,保证了查询操作的时间复杂度就会一直维持在 O(logn) 。但是它本质上还是一个二叉树,每个节点只能有 2 个子节点,随着元素的增多,树的高度会越来越高。
  而树的高度决定于磁盘 I/O 操作的次数,因为树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作,也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数,所以树的高度越高,就会影响查询性能。
  B 树和 B+ 都是通过多叉树的方式,会将树的高度变矮,所以这两个数据结构非常适合检索存于磁盘中的数据。
  但是 MySQL 默认的存储引擎 InnoDB 采用的是 B+ 作为索引的数据结构,原因有: B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。 B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 B+ 树在插入、删除的效率都更高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化; B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。
  完! 原文链接:https://mp.weixin.qq.com/s/w1ZFOug8-Sa7ThtMnlaUtQ
  原作者:小林coding

全系标配手机车钥匙,秦Pro超越版520上线5月20日,比亚迪秦Pro超越版正式上市。整车外观动感时尚,配置实用超前,还搭配了堪称黑科技的手机NFC车钥匙,官方价位仅为7。98万9。98万。值得一提的是,在6月30日前订车可哈弗F7销量再度破万累计销量突破18万4月,哈弗F7终端销售10,911辆,环比增长80,成为当月最热潮品SUV。迄今,哈弗F7累计销量已突破18万辆,并带动哈弗F系成为细分市场最具吸引力的SUV车型。疫情期间,哈弗F新一代智跑品质制胜起亚正埋头赶上车市脉动。在竞争最为激烈的SUV市场,新一代智跑上市一年销量破10万辆月均销量保持在6000辆以上,成为东风悦达起亚旗下表现最出色的产品。其中,产品品质与产品力的持续雕琢光影声色翼联EDUP1080P智能自动对焦摄像头上市报刊杂志跌落大众视野,书信短信已然明日黄花,数字网络将21世纪彻底点亮。走过缤纷静谧的图文时代,视频开启了人们遍览山河的上帝之眼,直播又让一场时光盛宴活灵活现。随着网络大幅提速升级测试结果流出你想知道的刀片电池安全测试都在这2020年3月刀片电池以征服针刺测试而广为人知,动力电池的安全性也由此备受关注。很多消费者想要了解更多刀片电池的安全信息,除了针刺测试之外,刀片电池还接受过哪些测试?表现如何呢?我六款车型同时首发恒大汽车务实再出发01hr造车新势力最大一匹黑马,恒大汽车迈出了坚实的一步。8月3日,恒大汽车6款新车同时全球首发,在汽车圈和金融界掀起一道道飓风。造车新势力已举步维艰?恒大汽车给出了有力的答案。百新平台新实力第十代索纳塔正式上市近日,北京现代第十代索纳塔正式上市,共5款车型,售价区间为16。18万20。58万元。新车定位智慧运动美学中高级座驾。作为现代汽车新一代iGMP平台下的首款量产车型,第十代索纳塔将造车驶入快车道!恒大健康更名为恒大汽车近来,恒大健康(0708。HK)可谓动作频频,利好不断。继大幅降低投资门槛至每手500股后,7月27日再发公告,公司名称更改为恒大汽车。分析认为,此举不仅标志着其主营业务已明确为新7月新车SUV主导,轿车K5凯酷比亚迪汉EV备受关注继6月车市迎来第一波新车高峰后,7月各厂商再次集中火力推出多款新车备战成都车展。SUV是今年车市最热门的市场。据DaasAuto达示数据梳理,7月新车共计42款,其中19款全新车型年味家乡味好运总相随翼联EDUP欢度元宵佳节红红火火过大年,欢欢喜喜闹元宵。2月26日,一场别开生面的元宵欢宴在翼联EDUP热烈举办。翼联舞台张灯结彩,来自五湖四海的翼家人踊跃报名,精心准备了各自的拿手好菜,团聚在一起,分享4G无处不在为何还用4GWiFi4G无线路由器上网更简单5G小荷尖尖,4G已成标配,4GWiFi是何方神圣?宽带网络日益普及,4GLTE无处不在,为何还用4GWiFi?畅玩4GWiFi更省电上网时,耗电量主要跟手机的发射功率有关。而发射
哲学家的疑惑粒子不断细分下去,到底有没有一个尽头?德国古典哲学家康德在纯粹理性批判中系统提出二律背反的现象,这是经验论和唯理论长期争执不下的四种命题。每一个命题都有两个对立且符合形式逻辑的解释。这种正反命题都合理且又对立的现象就叫太开心了!喜提五一6级88元大红包,老婆说晚上给我加两个鸡腿大家好,我是爱分享的教授。今天很高兴跟大家说一说我是怎么神奇地通过努力,顺利取得胜利的,并获得了88元大礼包(其实目前实际是92。56元),还在至继续膨胀之中呲牙这是几天天累计的红vivoXNote和三星S22UItra影像对比,都是大屏旗舰,差距有多大?国产手机影像已经达到了史无前例的高水平,在DXO影像排名中更是可以拿下世界第一,譬如华为P50Pro小米11UItravivoX70Pro等等旗舰手机,都堪称影像怪兽,那么作为大屏iOS15。4。1对旧iPhone友好吗?11款机型实测,看完再决定是否更新苹果已经为旗下的iPhone操作系统升级到了iOS15。4。1,理论上来说,系统是越新越好,因为之前旧款iPhone存在的很多问题,在iOS更新之后就可以得到解决。但是由于iPho人工智能AI是不是已经毁了围棋这一古老的游戏?社会发展,技术进步,AI出现。智能制造柔性制造得AI风气之先,然后扩展到机器人技术精细医疗远程医疗等等领域。在AI所过之处,有两类实际应用最能刺激到人类的神经。一是军事,无人机智能小米11Ultra降价1500元,太香了,但性能和颜值,vivoX80还是强今年发布的旗舰机型来看,vivoX80属于是赢麻了,在4000元左右价位,属于影像和性能兼顾的手机,而且外观颜值也耐看。一台颜值出众,性能拍照都在线的手机,很难让人不爱。但隔壁小米五一换机首选的4款千元手机,低价用出高端的感觉五一选购手机时,可千万别小看千元机。现在千元手机市场竞争激烈,性能也越来越强,很多旗舰配置都能在千元机里看到,推荐4款五一换机首选的千元手机,低价用出高端的感觉!一红米K40S价格40亿年前,太阳系曾有三个地球?科学家发现人类幸存者实属奇迹地球在整个宇宙中,是唯一诞生生命的星球,人类不断对宇宙进行探索,试图接收来自地外文明的信号,但在其他星球并没有发现任何生命迹象。难道,地球是宇宙中唯一孕育生命的行星吗?如果是这样,AMD的Zen3CPU很棒,为什么没有人使用呢?十几年了,CPU除了拉高主频外修修改改之外,没有质的跨越,每两年主频提升0。3g,英特尔十年前的主频都有3。3,现在5。2,不是搞生产换来换去浪费钱。如果每两年主频提升2g,这样算网易为什么要推出花语月和惊梦这种既无广告也无内购的免费单机游戏?这种行为可以视为网易对手机游戏细分领域的一次试水。花语月诞生于网易游戏学院MINI项目组,制作团队很小,只有一名策划,三名美术,三名程序和一名测试,制作人曹潇然也算是个新人。花语月soul咋样?真的能找到灵魂伴侣吗?用过,差不多几个月时间吧,但就打过一次语音。匹配的是同省另一个城市的大三小姑娘,当时我也才毕业。联系了一年,然后在一起了,现在谈了一年半的恋爱了,从认识开始每天都会打电话,基本每周