不懂数据库索引的底层原理?那是因为你心里没点b树

  • 时间:
  • 浏览:90
  • 来源:完美娱乐网_提供678辅助网技术_玩游戏赚钱资讯

  前几天下班回到家后正在出理 六个白天没出理 的bug,厕所老是传来对象的声音:

  对象:xx,你有《时间简史》吗?

  我:我去!妹子,你这啥癖好啊,我有时间就说 我会去捡屎啊!

  对象:...人家说的是霍金的科普著作《时间简史》,是一本书啦!

  我:哦,如果没人 ...

  对象:人家看得人诶,你明天让人去图书馆借一本吧...

  我:我明天还能不能 改...

  对象:你是都不 不爱我了,分手!

  我:我一大早就去~

  平衡二叉树是并是不是生活特殊的二叉树,好多好多 他也满足前面说到的二叉树的六个价值形式,一同还有六个价值形式:

  随着数据的不断写入,这棵树也逐渐枝繁叶茂,如下图

  从这一 流程亲们能看出,B-Tree的查询角度好像也暂且比平衡二叉树高。怎么能让查询所经过的结点数量要少好多好多 ,也就原因 要少好多好多 次的磁盘IO,这对

性能的提升是很大的。

  前面关于数据存储的都不 演示的聚集索引的实现,原因 上方的用户表还能不能 以“用户名字”建立六个非聚集索引,是为甚实现的呢?亲们看下图:

  原因 还能不能 查找六个元素,那流程是为甚样的呢?亲们看下图,原因 亲们要在下面的B-Tree中找到关键字24,那流程如下







  

  一颗平衡二叉树能容纳几只的结点呢?这跟树的角度是有关系的,假设树的角度为h,那每一层最多容纳的结点数量为2^(n-1),整棵树最多容纳节点数为2^0+2^1+2^2+...+2^(h-1)。如果计算,100w数据树的角度要花费在20左右,那也就说 我说从有着100w条数据的平衡二叉树中找六个数据,最坏的情形下还能不能 20次查找。原因 是内存操作,角度也是很高的!怎么能让亲们数据库中的数据基本都不 倒进磁盘中的,每读取六个二叉树的结点就说 我一次磁盘IO,如果亲们找两根数据原因 要经过20次磁盘的IO?那性能就成了六个很大的疑问了!如果们是都不 还能不能 把这棵树压缩一下,让每一层还能不能 容纳更多的节点呢?着实我矮,怎么能让我胖啊...

  原因 数据还比较少,六个页就能容下,好多好多 不还能不能 六个根结点,主键和数据也都不 保位于根结点(左边的数字代表主键,右边名字、性别代表具体的数据)。假设亲们写入10条数据如果,Page1满了,再写入新的数据会为甚存放呢?亲们继续看下图

  原因 上方B-Tree的图变成B+Tree,那应该如下:

  数据插入了为甚查找呢?

  我到楼上后又看得人每排的书架上又对书的分类进行了细分,如果让人调慢的定位到让人找的书具体在哪个书架!

  好多好多 当亲们要找主键为6的记录时,先通过二分法稀疏索引中找到对应的槽,也就说 我Page Directory中“8”这一 槽,“8”这一 槽指向的是该数据块中最大的记录,而数据是单向链表价值形式好多好多 无法逆向查找,好多好多 还能不能 找到上六个槽即“4”这一 槽,怎么能让通过“4”这一 槽中最大的用户记录的指针沿着链表顺序查找到目标记录。













  亲们老是会在好多好多 的文章或书中能看得人这一索引的使用建议,比如说

  没人 大的图书馆,我为这一 能在没人 短的时间内找到让人的书?原因 这一 书是杂乱无章的堆放,原因 没人 任何标识的倒进书架,我还能没人 快的找到吗?

  B+Tree是在B-Tree基础上的并是不是生活优化,使其更适合实现外存储索引价值形式。B+Tree与B-Tree的价值形式很像,怎么能让都不 几只我所其他同学的价值形式:

  在InnoDB存储引擎中,都不 页的概念,默认每个页的大小为16K,也就说 我每次读取数据时都不 读取4*4k的大小!假设亲们现在有六个用户表,亲们往上方写数据

  是都不 感觉跟丈母娘张口谁能告诉让人彩礼一样,列一堆的条件,怎么能让每两根都让人很懵逼!下面亲们以六个[0,1,2,3,4,5,6,7]的数组插入一颗3阶的B-Tree为例,将所有的条件都串起来,你就明白了!

1、主键索引树的叶子结点的数据区域没人 存放实际的数据,存放的是数据记录的地址。

2、数据的存储都不 按主键顺序存放的,按写入的顺序存放。

1、每个结点最多m个子结点。

2、除了根结点和叶子结点外,每个结点要花费有m/2(向上取整)个子结点。

3、原因 根结点都不 叶子结点,那根结点要花费含有六个子结点。

4、所有的叶子结点都位于同一层。

5、每个结点都含有k个元素(关键字),这里m/2≤k<m,这里m/2向下取整。

6、每个节点中的元素(关键字)从小到大排列。

7、每个元素(关键字)字左结点的值,都小于或等于该元素(关键字)。右结点的值都大于或等于该元素(关键字)。

  每个行记录的都不 六个n_owned的区域(图中粉红色区域),n_owned标识这一 这一 块有几只条数据,伪记录Infimum的n_owned值老是1,记录Supremum的n_owned的取值范围为[1,8],这一用户记录n_owned的取值范围[4,8],怎么能让不还能不能 每个块中最大的那条记录的n_owned才会有值,这一的用户记录的n_owned为0。

  

  图中的这一 名字均来源于网络,希望没人 误伤正在看这篇文章的你~^_^

  上图为MyISAM主键索引的存储价值形式,亲们能看得人的不同是

它的左右六个子树的角度差的绝对值不超过1,怎么能让左右六个子树都不 一棵平衡二叉树。

  好多好多 这里就不一一列举了!那看得人这篇文章,亲们还能不能 带着疑问去分析一下为这一 要有这一 建议?为这一 like的模糊查询以%开头,会原因 索引失效?为这一 六个表建的索引尽量暂且超过六个?为这一 ? 为这一 ??为这一 ???相信看得人这里的你加上上我所其他同学的这一思考应该有答案了吧?

  B-Tree和B+Tree该怎么还能不能选着呢?都不 这一 优劣呢?

  1、B-Tree原因 非叶子结点也保存具体数据,好多好多 在查找某个关键字的如果找到即可返回。而B+Tree所有的数据都不 叶子结点,每次查找都得到叶子结点。好多好多 在同样角度的B-Tree和B+Tree中,B-Tree查找某个关键字的角度更高。

  2、原因 B+Tree所有的数据都不 叶子结点,怎么能让结点之间有指针连接,在找大于某个关键字原因 小于某个关键字的数据的如果,B+Tree只还能不能 找到该关键字怎么能让沿着链表遍历就还能不能 了,而B-Tree还能不能 遍历该关键字结点的根结点去搜索。

  3、原因 B-Tree的每个结点(这里的结点还能不能 理解为六个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,好多好多 同一页能存储的B-Tree的数据会比B+Tree存储的更少。如果同样总量的数据,B-Tree的角度会更大,增大查询时的磁盘I/O次数,进而影响查询角度。

  鉴于以上的比较,好多好多 在常用的关系型数据库中,都不 选着B+Tree的数据价值形式来存储数据!下面亲们以mysql的innodb存储引擎为例讲解,这一这一sqlserver、oracle的原理这一!

  那原因 按照[12 27 29 35 38 48 55]的顺序插入一颗平衡二叉树,会为甚样呢?亲们看看插入以及平衡的过程:

  怎么能让每个楼层都不 一台查询终端,输入书名就能查到对应的唯一标识“索书号”,这一于P159-49/164如果的六个编码,书架上的书都不 按照这一 编码进行排序的!有了这一 编码再去对应的书架上,调慢就能找到对应的书在书架的具体位置了。

  这跟亲们在新华字典中找某个汉字是一样的,先通过字典的索引定位到该汉字拼音所在的页,怎么能让到指定的页找到具体的汉字。innodb中定位到页后用了哪种策略快速查找某个主键呢?这亲们就还能不能 从页价值形式结速了了解。

  那B-Tree有这一 价值形式呢?一棵m阶的B-Tree有如下价值形式:

  要了解数据库索引的底层原理,亲们就得先了解并是不是生活叫树的数据价值形式,而树中很经典的并是不是生活数据价值形式就说 我二叉树!好多好多 下面亲们就从二叉树到平衡二叉树,再到B-树,最后到B+树来一步一步了解数据库索引底层的原理!

  也就说 我说innodb引擎数据在物理上是按主键顺序存放,而MyISAM引擎数据在物理上按插入的顺序存放。怎么能让MyISAM的叶子结点不存放数据,好多好多 非聚集索引的存储价值形式与聚集索引这一,在使用非聚集索引查找数据的如果通过非聚集索引树就能直接找到数据的地址了,不还能不能 回表,这比innodb的搜索角度会更高呢!

  亲们仔细对比于B-Tree的图能发现这一 不同?

  1、非叶子结点上原因 不还能不能 key信息了,满足上方第1点价值形式!

  2、所有叶子结点下面都不 六个data区域,满足上方第2点价值形式!

  3、非叶子结点的数据在叶子结点上都能找到,如根结点的元素4、8在最底层的叶子结点上还能不能 找到,满足上方第3点价值形式!

  4、注意图中叶子结点之间的箭头,满足满足上方第4点价值形式!

  前面对B-Tree操作的图亲们能看出来,元素就说 我这一1、2、3如果的数值,怎么能让数据库的数据都不 两根条的数据,原因 某个数据库以B-Tree的数据价值形式存储数据,那数据为甚存放的呢?亲们看下一张图

1、每个结点都含有六个元素以及n个子树,这里0≤n≤2。

2、左子树和右子树是有顺序的,次序不还能不能 任意颠倒。左子树的值要小于父结点,右子树的值要大于父结点。

1、所有的非叶子节点只存储关键字信息。

2、所有卫星数据(具体数据)都位于叶子结点中。

3、所有的叶子结点含有有了完正元素的信息。

4、所有叶子节点之间都不 六个链指针。

  没人 ,你是是是不是对B-Tree的几点价值形式都清晰了呢?在二叉树中,每个结点不还能不能 六个元素。怎么能让在B-Tree中,每个结点都原因 含有多个元素,怎么能让非叶子结点在元素的左右都不 指向子结点的指针。

  二叉树是每个结点最多有六个子树的树价值形式。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。二叉树有如下价值形式:

  这不禁让人能到了亲们开发中用到的数据库,图书馆的书就这一亲们数据表中的数据,楼层索引牌、书架分类标识、索书号就这一亲们查找数据的索引。

  第五六天一大早让人到了图书馆,刚进门看得人得人六个索引牌,标识着不同楼层的功能,如果我调慢能定位到让人找的目标所在的楼层了。

  左边浅绿色区域称为Page Directory,这块区域由多个slot组成,是六个稀疏索引价值形式,即六个槽中原因 属于多个记录,要花费属于4条记录,最多属于8条记录。槽内的数据是有序存放的,好多好多 当亲们寻找两根数据的如果还能不能 先在槽中通过二分法查找到六个大致的位置。

  如果们常用的数据库的索引底层的六个数据价值形式是这一 样的呢?想到这里我又回到图书馆借了一本《数据库从入门到放弃》!

  原因 是升序插入,新插入的数据老是比已位于的结点数据都不 大,好多好多 每次后要往结点的右边插入,最终原因 这棵树严重偏科!!!上图就说 我最坏的情形,也就说 我一棵树退化为六个线性链表了,如果查找角度自然就低了,完正没人 发挥树的优势了呢!

为了较大发挥二叉树的查找角度,让二叉树不再偏科,保持各科平衡,好多好多 有了平衡二叉树!

  右边区域为数据区域,每六个数据页中都含有多条行数据。注意看图中最上方和最下面的两条特殊的行记录Infimum和Supremum,这是六个虚拟的行记录。在没人 这一用户数据的如果Infimum的下两根记录的指针指向Supremum,当有用户数据的如果,Infimum的下两根记录的指针指向当前页中最小的用户记录,当前页中最大的用户记录的下两根记录的指针指向Supremum,至此整个页内的所有行记录形成六个单向链表。

  这棵树的非叶子结点上存的都不 主键,那原因 六个表没人 主键会为甚样?在innodb中,原因 六个表没人 主键,那默认会找建了唯一索引的列,原因 也没人 ,则会生成六个隐形的字段作为主键!

  有数据插入那都不 删除,原因 这一 用户表频繁的插入和删除,那会原因 数据页产生碎片,页的空间利用率低,后要原因 树变的“虚高”,降低查询角度!这还能不能 通过索引重建来消除碎片提高查询角度!

  这棵树始终满足平衡二叉树的几只价值形式而保持平衡!如果亲们的树就说 我会退化为线性链表了!亲们还能不能 查找六个数的如果就能沿着树根老是往下找,如果的查找角度和二分法查找是一样的呢!

  普通的B-Tree的结点中,元素就说 我六个个的数字。怎么能让上图中,亲们把元素每段拆分成了key-data的形式,key就说 我数据的主键,data就说 我具体的数据。如果亲们在找两根数的如果,就沿着根结点往下找就ok了,角度是比较高的。

  不还能不能 十分钟,让人从图书馆借好书出来了。

本文在我所其他同学技术博客不同步发布,详情可用力戳

亦可扫描屏幕右侧二维码关注我所其他同学公众号,公众号内有我所其他同学联系土办法,等你来撩...

1、like的模糊查询以%开头,会原因 索引失效。

2、六个表建的索引尽量暂且超过六个。

3、尽量使用覆盖索引。

4、尽量暂且在重复数据多的列上建索引。

5、。。。。。。。。。。。

6、。。。。。。。。。。。

  怎么能让原因 同样是上方那一组数,亲们我所其他同学升序排列后再插入,也就说 我说按照[12 27 29 35 38 48 55]的顺序插入,会为甚样呢?

  这颗矮胖的树就说 我B-Tree,注意上方是杠精的杠而都不 减,好多好多 就说 我要读成B减Tree了~

  亲们也看得人了前面[35 27 48 12 29 38 55]插入完成后的图,着实就原因 是一颗平衡二叉树啦。

  在讲这一 种生活数据价值形式在数据库中的选着如果,亲们还能不能 了解的六个知识点是操作系统从磁盘读取数据到内存是以磁盘块(block)为基本单位的,位于同六个磁盘块中的数据会被一次性读取出来,而都不 还能不能 这一 取这一 。即使只还能不能 六个字节,磁盘也会从这一 位置结速了,顺序向后读取一定长度的数据倒进内存。如果做的理论土办法是计算机科学中著名的局部性原理: 当六个数据被用到时,其随近的数据也通常会马上被使用。

  预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在这一操作系统中,页得大小通常为4k)。

  每次新增数据,都不 将六个页写满,怎么能让新创建六个页继续写,这里着实是有个隐含条件的,那就说 我主键自增!主键自增写入时新插入的数据不用影响到原有页,插入角度高!且页的利用率高!怎么能让原因 主键是无序的原因 随机的,那每次的插入原因 会原因 原有页频繁的分裂,影响插入角度!降低页的利用率!这也是为这一 在innodb中建议设置主键自增的原因 !

  有个叫“秦寿生”的亲们来了,怎么能让Page1原因 放不下数据了,这如果就还能不能 进行页分裂,产生六个新的Page。在innodb中的流程是为甚样的呢?

  非聚集索引的存储价值形式与前面是一样的,不同的是在叶子结点的数据每段存的不再是具体的数据,而数据的聚集索引的key。好多好多 通过非聚集索引查找的过程是先找到该索引key对应的聚集索引的key,怎么能让再拿聚集索引的key到主键索引树上查找对应的数据,这一 过程称为回表

  光看概念有点痛 枯燥,假设亲们现在有如果一组数[35 27 48 12 29 38 55],顺序的插入到六个数的价值形式中,步骤如下

























  好了,这就说 我一棵二叉树啦!亲们能看得人,经通过一系列的插入操作如果,如果无序的一组数原因 变成六个有序的价值形式了,怎么能你会这一 树满足了上方提到的六个二叉树的价值形式!

  行记录被Page Directory逻辑的分成了多个块,块与块之间是有序的,也就说 我说“4”这一 槽指向的数据块内最大的行记录的主键都不 比“8”这一 槽指向的数据块内最小的行记录的主键要小。怎么能让块外部的行记录不一定有序。

  上方包括存储和搜索都不 拿的innodb引擎为例,那MyISAM与innodb在存储上有啥不同呢?憋缩话,看图:

  这里还能不能 注意的这一是,在某个页内插入新行时,为了不减少数据的移动,通常是插入到当前行的上方原因 是已删除行留下来的空间,好多好多 在某六个页内的数据并都不 完正有序的(上方页价值形式每段有细讲),怎么能让为了为了数据访问顺序性,在每个记录中都不 六个指向下两根记录的指针,以此构成了两根单向有序链表,不过在这里为了方便演示我是按顺序排列的!

  2、如果Page1有10条数据,在插入第11条数据的如果进行裂变,根据前面对B-Tree、B+Tree价值形式的了解,那这要花费是一颗11阶的树,裂变如果每个结点的元素要花费为11/2=六个,那是都不 应该页裂变如果主键1-5的数据还是在如果的页,主键6-11的数据会倒进新的页,根结点存放主键6?

  原因 是如果得话新的页空间利用率不还能不能 100%,怎么能让会原因 更为频繁的页分裂。好多好多 innodb对这一 点做了优化,新的数据倒进新创建的页,不移动原有页面的任何记录。

  这里有六个疑问还能不能 注意的是

  1、为这一 要克隆好友Page1为Page2而都不 创建六个新的页作为根结点,如果就少了一步克隆好友的开销了?

  原因 是重新创建根结点,那根结点存储的物理地址原因 老是会变,不促进查找。怎么能让在innodb中根结点是会预读到内存中的,好多好多 结点的物理地址固定会比较好!

1、产生新的Page2,怎么能让将Page1的内容克隆好友到Page2。

2、产生新的Page3,“秦寿生”的数据倒进Page3。

3、如果的Page1依然作为根结点,怎么能让变成了六个不存放数据只存放索引的页,怎么能让有六个子结点Page2、Page3。

1、找到数据所在的页。这一 查找过程就跟前面说到的B+Tree的搜索过程是一样的,从根结点结速了查找老是到叶子结点。

2、在页内找具体的数据。读取第1步找到的叶子结点数据到内存中,怎么能让通过分块查找的土办法找到具体的数据。