MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?

平衡二叉树

(1)非叶子节点最多拥有两个子节点;

(2)非叶子节值大于左边子节点、小于右边子节点;

(3)树的左右两边的层级数相差不会大于1;因为平衡二叉树查询性能和树的层级(h高度)成正比、为了保证树的结构左右两端数据大致平衡降低二叉树的查询难度一般会采用一种算法机制实现节点数据结构的平衡

(4)没有值相等重复的节点;

 索引

索引(Index)是帮助MySQL高效获取数据的数据结构。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构

定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同数据记录,key是互不相同的;data为数据记录除key外的数据

 

B树(B-tree)

B树和平衡二叉树稍有不同的是B树属于多叉树又名平衡多路查找树(查找路径不只两个)

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

(1)在一个节点中,存放着数据(包括key和data)以及指针,且相互间隔

(2)同一个节点,key增序

(3)一个节点最左边的指针不为空,则它指定的节点左右的key小于最左边的key。右边同理。中间的指针指向的节点的key位于相邻两个key的中间。

(4)B-Tree中不同节点存放的key和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中B-Tree往往对每个节点申请同等大小的空间

(5)每个非叶子节点由n-1个key和n个指针组成,其中d<=n<=2d

 数据库B-Tree检索

按key检索数据,首先与根节点key比较,如果找到则返回对应节点的data,否则对相应区间的指针指向的节点递归进行查找,直到找到节点或找到null指针,前者查找成功,后者查找失败

  B+树

内节点不存储data,只存储key和指针;叶子节点不存储指针,存key和data

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

(1)内节点和叶子节点大小不同 

(2)每个节点的指针上限为2d而不是2d+1

(3)因为它节点内部没有data,所以有更多的空间放key,所以B+树的出度一般比B-树要大,而对于一定的数据,出度大的话,树的深度就小,所以B+树的检索效率比B-树高

 数据库B+Tree检索 

 般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针

提高区间访问的性能,例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

 

 为什么使用B-Tree(B+Tree)做索引?

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上,换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。

先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h(树的深度)个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个节点只需一次I/O。

B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(h)。一般实际应用中,出度d(节点最大的分支数)是非常大的数字,通常超过100,因此h非常小(通常不超过3)。

综上所述,用B-Tree作为索引结构效率是非常高的。

而红黑树这种结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。

上文还说过,B+Tree更适合外存索引,原因和内节点出度d有关。从上面分析可以看到,d越大索引的性能越好,而出度的上限取决于节点内key和data的大小。

MySQL索引实现

MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构,MyISAM索引文件仅仅保存数据记录的地址,我们假设数据有3列,且Col1是主键,这个图就是主键的索引结构示意图,上文的key对应主键的值,叶节点的data域存放的是数据记录的地址。

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

 

MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分

 InnoDB索引实现

也是使用B+树实现索引结构,但是实现方式与上面不同,聚集索引

即data不存地址,而是直接存数据本身,即数据文件就是索引文件,

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。下图是以第二列为主键的辅助索引,即主键与第二列之间的对应关系,当然在MyISAM也可以建立辅助索引

《MYSQL(一)-------为什么使用B+树或者B-树做为索引结构?》

 聚集索引这种实现方式使得按主键的搜索十分高效,

但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

 

 

    原文作者:B树
    原文地址: https://blog.csdn.net/wangdongli_1993/article/details/81145563
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注