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

女朋友问我为什么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

12月27星期二最新早上好图片带字高清新的一天愿我们前路一片光明1世事沧桑,不过斗转星移,繁花落尽,拾起烟火笑意。余生很长,太阳下山,还有月光峰回路转,来日方长。乐观做事,善良待人。愿我们前路一片光明!早安!2心若放宽,时时都是晴天。人生不一定2023年楼市将反转,对于老百姓真的利好吗?有人是看衰2023年的楼市,为什么呢?因为它基于2022年楼市的判断,整个2022年我们的楼市是处于全面放开的状态,可是呢,我们整体买房子的意愿是比较低的,大家呢都观望,所以会觉得安卓微信8。0。32内测地图新增室内显示等多项更新!给你们最新最快的安卓微信内测更新资讯!距离2023年是越来越近,本次的安卓微信内测新版本发布,本次的内测将会是2022年最后一个内测版本,大家应该也注意到了iOS微信8。0。32版屡遭背叛不离婚,蒋雯丽和导演丈夫的29年婚姻,就像一场博弈娱乐圈女明星,嫁导演丈夫后,当会遇到同样的麻烦被背叛。对于导演丈夫的出轨,徐帆谈及表示我不怕冯小刚出轨,担心也没用,反正我家是男的,吃亏的不是我们。与此同时,陶虹也说过很多女人往徐2022娱乐圈祸从口出系列宋丹丹窒息,张雨绮偏激,贾乃亮无知开播一周,掉粉近百万,多年维持的形象毁于一旦。向太用实力诠释,什么叫祸从口出。直播带货本就考验一个人的情商,向太却不合时宜玩梗汪小菲与大S,被张兰怼,被网友烦,钱赚了多少不知道,骂电影战狼中最不真实的一幕,警察拔枪对准正装解放军军官电影战狼中最不可思议的一幕,发生在开头的拆迁现场,拆迁队正在强拆烈士的家,烈士一家人哭哭啼啼不知所措。正在这时解放军中尉军官冷锋奉命送烈士的骨灰回家,正好遇上了这场强拆。这个拆迁队未婚生育子女?现已怀有身孕?韩网深扒宋仲基女友背景收获满满此前26日,演员宋仲基方面承认了与英国女友的恋爱关系,经纪公司称两人一直保持着良好的感情。希望大家能够以温暖的视线来看待除了交往事实以外,无法确认其他信息,敬请谅解。请克制未经确认整容后遗症开始凸显,牛莉演艺事业的下坡路或才刚刚开始!人到中年后,女演员一般都会冲着两个方面努力其一,如梅婷郝蕾一般,努力精修演技,想再次通过演技一鸣惊人。近日,关于梅婷演技登上热搜,当人们还沉浸在不要和陌生人说话中的被欺负的角色时,抖音突袭,华为入局网约车有了新内涵作者肖卓一则在抖音上打网约车或将成为现实的消息,让本就不平静的网约车行业再起波澜。12月26日,Tech星球报道称,抖音已经开放交通出行服务的平台服务商入驻资格,T3出行已在抖音A世界杯的冠军领奖台上,什么时候能看到中国人的身影?足球,中国古代名为蹴鞠,说2004年初中国足联确定足球起源于中国,蹴鞠也是有史料记载的的最早的体育运动。作为世界第一体育运动,足球带给一个国家和人民的影响力也是有目共睹的。2022看2023丨盛虹缪汉根加快打造世界一流新能源新材料产业集群站在2022岁末,看2023年,企业家作为中国经济的重要力量,如何看待当前的中国经济政策,对未来中国经济有何期待?新京报贝壳财经邀请百余位来自各行各业的企业家,以问卷方式完成对新一
NBA东部排名榜绿军威胁雄鹿榜首,76人篮网战绩相同,2队垫底11月13日,8场常规赛结束后,东部排名榜再次发生变化雄鹿榜首但已受到威胁,凯尔特人紧追其后,仅落后0。5个胜场差,坐二望一活塞和黄蜂继续垫底东部排名榜76人篮网热火同日取胜,战绩杨鸣眼光真毒,2米18中锋难堪大用,回到山东被弃用,只出场4分钟头条创作挑战赛山东男篮第一阶段的表现和战绩都不错,但有一名球员却比较失落,他就是本赛季重返球队的中锋朱荣振。本来经过在辽宁男篮的历练后,不少山东球迷都希望朱荣振能够有所成长,归队后20222023雪季将至吉林省冰雪地图精彩纷呈践行冰天雪地也是金山银山理念,吉林省委省政府高度重视冰雪经济高质量发展,扎实推进冬奥在北京,体验在吉林,发展在吉林。时值立冬,走进吉林大地,各大雪场度假区正在为即将到来的20222一味中药,常用于多种癌症治疗,包括肝癌胃癌直肠癌大家好,我是中医博士王佰庆。今天给大家分享一个抗癌中药猫人参,虽然它这个名字里带一个参字,但是它和中药人参是截然不同的中药材。这味中药的药用部位在于根部,味苦涩,性凉,入肝脾胃膀胱11月发育路梯队姐妹花跌落T0,黄忠和马可提前过年注T1的意思是指版本第一梯队的英雄,这类英雄会比普通英雄较为强势,而T0的意思是指凌驾于第一梯队,属于版本非ban必选的英雄。本榜单是结合了官方所公布的排位巅峰赛数据和KPL职业赛迭代衍生长征七号火箭能力越来越强来源央视网央视网消息此次发射天舟五号货运飞船的是长征七号运载火箭,这也是它执行的第六次发射任务。从首飞至今,研制团队不断对火箭进行优化和改进,使火箭更加安全可靠。长征七号运载火箭是每日一味抗癌中药虎耳草,生于林下灌丛,组方用于多种肿瘤虎耳草品种来源虎耳草科植物虎耳草的全草。全年可采,但花以后采者为好。将全草拔出,洗净,鲜用或晒干备用。别名石荷叶金丝荷叶狮子耳耳聋草金丝吊芙蓉。性味味苦,辛,性寒,有小毒。归经归肺一味清热解毒消肿散结的中药龙葵农村山里有种野果,有人叫它老鸦眼睛草天天茄等。其实它不仅仅是一种野果,它的保健和药用价值很高,一整棵植物都可以入药。它就是龙葵,其主要功用是除痰散结,利水消肿,所以,可以用于辅助治湿气多,毛病生,建议天冷吃4样,寒气减精神足,安然过冬人不管走到哪一步,总得找点乐子,想一点办法。是的,美食就是我找的乐子,想的办法!小谈食刻和你一起认真对待吃下的食物!导读随着气温不断的下降,冬天也越来越近了,秋冬季节,在人们眼中,一旦走出精神内耗,你的人生会有多爽?一个3年精神内耗者的自述作为一个资深的精神内耗者,我用了3年的时间来打磨自己的精神世界,最终彻底走出了精神内耗。没想到人生竟然突然起飞,爽到让我自己都不敢相信的地步。今天开始,我就把我走出精神内耗的方法,从张益唐说知识分子精神2022年11月7日,数学家张益唐长达111页的论文离散平均估计和朗道西格尔零点(DiscretemeanestimatesandtheLandauSiegelzero)在预印本平