为什么Mysql用B+树做索引而不用B-树或红黑树或hash

目录

 

1、定义

2、索引数据结构

3、为什么使用B Tree(B+Tree)

4、索引分类

5、聚集索引和非聚集索引

1、非聚集索引

2、聚集索引

B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。

 

AVL 数和红黑树基本都是存储在内存中才会使用的数据结构。

 

为什么不用hash

 


1、定义

索引是一种数据结果,帮助提高获取数据的速度

为了提高查找速度,有很多查询优化算法。但是每种查找算法都只能应用于特定数据结构之上。

索引就是数据库创建的满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据

2、索引数据结构

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

相关概念介绍

  • B-树(B树):多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;
  • B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;
  • B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;

3、为什么使用B Tree(B+Tree)

红黑树也可用来实现索引,但是文件系统及数据库系统普遍采用B/+Tree,为什么?

一般来说,索引本身也很大,不可能全存内存,往往以索引文件的形式存在磁盘

 (1)单节点能存储更多数据,使得磁盘IO次数更少。

 (2)叶子节点形成有序链表,便于执行范围操作。

 (3)聚集索引中,叶子节点的data直接包含数据;非聚集索引中,叶子节点存储数据地址的指针。

4、索引分类

1.普通索引index :加速查找

2.唯一索引

    主键索引:primary key :加速查找+约束(不为空且唯一)

    唯一索引:unique:加速查找+约束(唯一)

3.联合索引

    -primary key(id,name):联合主键索引

    -unique(id,name):联合唯一索引

    -index(id,name):联合普通索引

5、聚集索引和非聚集索引

聚集索引和非聚集索引使用的都是B+树结构。

1、非聚集索引

非聚集索引的叶子节点为索引节点,但是有一个指针指向数据节点。

MyISAM是非聚集索引。

2、聚集索引

聚集索引叶子节点就是数据节点。

关于聚集索引,innodb会按照如下规则进行处理: 
  1,如果一个主键被定义了,那么这个主键就是作为聚集索引 
  2,如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引 
  3,如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。
 

innodb的普通索引,唯一索引,联合索引都是辅助索引,采用非聚集索引结构。InnoDB的所有辅助索引都引用主键作为data域。

聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。 

 

B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。

 

所以从Mysql(Inoodb)的角度来看,B+树是用来充当索引的,一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上。 
那么Mysql如何衡量查询效率呢?– 磁盘IO次数。 B-树/B+树 的特点就是每层节点数目非常多,层数很少,目的就是为了就少磁盘IO次数,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时),而B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少。这是优点之一。 
另一个优点是: B+树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来。这样遍历叶子节点就能获得全部数据,这样就能进行区间访问啦。在数据库中基于范围的查询是非常频繁的,而B树不支持这样的遍历操作。

B树相对于红黑树的区别

AVL 数和红黑树基本都是存储在内存中才会使用的数据结构

 

在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。为什么会出现这样的情况,我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写。磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读写。根据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度,B树可以有多个子女,从几十到上千,可以降低树的高度。读盘的时间分布叫寻道时间,旋转延迟和传输时间,三者的时间是依次减少的

1.寻道时间: 磁头 从开始移动到数据所在 磁道 所需要的时间, 寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms、当前服务器已经可达3ms了。

2.旋转延迟: 盘片旋转将请求数据所在 扇区 移至读写 磁头 下方所需要的时间, 旋转延迟取决于 磁盘转速、当前服务器已经可达15000rpm。

3.数据传输时间:完成传输所请求的数据所需要的时间。

数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

 

为什么不用hash

 

问题1:MySQL中存储索引用到的数据结构是B+树,B+树的查询时间跟树的高度有关,是log(n),如果用hash存储,那么查询时间是O(1)。既然hash比B+树更快,为什么mysql用B+树来存储索引呢?

答:一、从内存角度上说,数据库中的索引一般时在磁盘上,数据量大的情况可能无法一次性装入内存,B+树的设计可以允许数据分批加载。

二、从业务场景上说,如果只选择一个数据那确实是hash更快,但是数据库中经常会选中多条这时候由于B+树索引有序,并且又有链表相连,它的查询效率比hash就快很多了。

 

感谢:

1、https://www.cnblogs.com/wangzhongqiu/archive/2019/04/22/10728569.html

2、https://blog.csdn.net/xiedelong/article/details/81417049

3、https://www.cnblogs.com/leijiangtao/p/4662779.html

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值