zoukankan      html  css  js  c++  java
  • MySQL数据库中索引的数据结构是什么?(B树和B+树的区别)

    B树(又叫平衡多路查找树)

    注意B-树就是B树,-只是一个符号。

    B树的性质(一颗M阶B树的特性如下)

    1、定义任意非叶子结点最多只有M个儿子,且M>2; 
    2、根结点的儿子数为[2, M]; 
    3、除根结点以外的非叶子结点的儿子数为[M/2, M]; 
    4、每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字) 
    5、非叶子结点的关键字个数=指向儿子的指针个数-1; 
    6、非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1]; 
    7、非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树; 
    8、所有叶子结点位于同一层;

    B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已经是叶子结点;

    B-树的特性:

    1.关键字集合分布在整颗树中;

    2.任何一个关键字出现且只出现在一个结点中;

    3.搜索有可能在非叶子结点结束;

    4.其搜索性能等价于在关键字全集内做一次二分查找;

    B+树

    (1)简介

    B+树是应文件系统所需而产生的一种B树的变形树(文件的目录一级一级索引,只有最底层的叶子节点(文件)保存数据)非叶子节点只保存索引,不保存实际的数据,数据都保存在叶子节点中,这不就是文件系统文件的查找吗?

    我们就举个文件查找的例子:有3个文件夹a、b、c, a包含b,b包含c,一个文件yang.c,a、b、c就是索引(存储在非叶子节点), a、b、c只是要找到的yang.c的key,而实际的数据yang.c存储在叶子节点上。

    所有的非叶子节点都可以看成索引部分!

    (2)B+树的性质(下面提到的都是和B树不相同的性质)

    1、非叶子节点的子树指针与关键字个数相同; 
    2、非叶子节点的子树指针p[i],指向关键字值属于[k[i],k[i+1]]的子树.(B树是开区间,也就是说B树不允许关键字重复,B+树允许重复); 
    3、为所有叶子节点增加一个链指针; 
    4、所有关键字都在叶子节点出现(稠密索引). (且链表中的关键字恰好是有序的); 
    5、非叶子节点相当于是叶子节点的索引(稀疏索引),叶子节点相当于是存储(关键字)数据的数据层; 
    6、更适合于文件系统;

    非叶子节点(比如5,28,65)只是一个key(索引),实际的数据存在叶子节点上(5,8,9)才是真正的数据或指向真实数据的指针。

    应用  

    1、B和B+树主要用在文件系统以及数据库做索引,比如MySQL;(MySQL使用B+树)

    B/B+树性能分析

    n个节点的平衡二叉树的高度为H(即logn),而n个节点的B/B+树的高度为logt((n+1)/2)+1; 
    若要作为内存中的查找表,B树却不一定比平衡二叉树好,尤其当m较大时更是如此。因为查找操作CPU的时间在B-树上是O(mlogtn)=O(lgn(m/lgt)),而m/lgt>1;所以m较大时O(mlogtn)比平衡二叉树的操作时间大得多。因此在内存中使用B树必须取较小的m。(通常取最小值m=3,此时B-树中每个内部结点可以有2或3个孩子,这种3阶的B-树称为2-3树)。

    为什么说B+树比B树更适合数据库索引?

    1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

    2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

    3、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

    PS:我在知乎上看到有人是这样说的,我感觉说的也挺有道理的:

    他们认为数据库索引采用B+树的主要原因是:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。

     
     

    今天看了几篇文章,自己总结一下。

    数据库使用B+树肯定是为了提升查找效率。

    但是具体如何提升查找效率呢?

    查找数据,最简单的方式是顺序查找。但是对于几十万上百万,甚至上亿的数据库查询就很慢了。

    所以要对查找的方式进行优化,熟悉的二分查找,二叉树可以把速度提升到O(log(n,2)),查询的瓶颈在于树的深度,最坏的情况要查找到二叉树的最深层,由于,每查找深一层,就要访问更深一层的索引文件。在多达数G的索引文件中,这将是很大的开销。所以,尽量把数据结构设计的更为‘矮胖’一点就可以减少访问的层数。在众多的解决方案中,B-/B+树很好的适合。B-树定义具体可以查阅,简而言之就是中间节点可以多余两个子节点,而且中间的元素可以是一个域。相比B-树,B+树的父节点也必须存在于子节点中,是其中最大或者最小元素,B+树的节点只存储索引key值,具体信息的地址存在于叶子节点的地址中。这就使以页为单位的索引中可以存放更多的节点。减少更多的I/O支出。因此,B+树成为了数据库比较优秀的数据结构,MySQL中MyIsAM和InnoDB都是采用的B+树结构。不同的是前者是非聚集索引,后者主键是聚集索引,所谓聚集索引是物理地址连续存放的索引,在取区间的时候,查找速度非常快,但同样的,插入的速度也会受到影响而降低。聚集索引的物理位置使用链表来进行存储。

    参考链接:

    https://www.2cto.com/net/201808/773535.html

    https://www.cnblogs.com/tiancai/p/9024351.html

  • 相关阅读:
    Vagrant box ubuntu/xenial64 添加vagrant用户解决没有登录密码的问题
    jQuery获取浏览器URL链接的值
    js防止客户端多触发
    Jquery实现一组复选框单选
    jQuery监听文本框值改变触发事件(propertychange)
    将http调用返回json中的有关中文的unicode转换为中文
    Visual Studio 2015 Bowser Link的功能不停的向服务端发送请求
    客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)
    java集群之session共享解决方案
    阻止保存要求重新创建表的更改选项
  • 原文地址:https://www.cnblogs.com/linliquan/p/11364428.html
Copyright © 2011-2022 走看看