本文是承接MySQL高新能索引这篇文章的部分内容,单独抽离出来分析MySQL为什么使用B+树,在上文中有提到索引有hash、二叉树、B树(B-树),B+树,而MySQL使用的是B+树,本文就对应这个进行分析!
Hash索引其实就是依赖于Hash表的关于Hash这块详细的可以查看往期文章HashMap底层数据结构(数组+链表+红黑树),这里还是讲解下Hash索引,如下
首先Hash表是一组连续的数组,对要存入的值进行hash取值然后%上Hash的长度,那么得到的余数就对应着Hash
表的下标位置,这是最简单的Hash存储方式,当我们存储的数据量过大的时候,那么就会产生哈希碰撞,那么不同的值就会的到相同的Hash,那么同样也会得到相同的下标,那么这就衍生出了链表和红黑树,关于这其中的细节,在上文中有详细的介绍!MySQL为什么不采用Hash的方式存储索引呢?如下!(并非不支持Hash索引,如Memory引擎就以Hash作为默认索引类型存储,同时支持B-树,值得一提的是Memory引擎是支持的非唯一哈希索引,除Memory引擎之外,NDB集群引擎也支持唯一Hash索引,关于这里不展开说了。)
缺点
注意本文并不是讲这些树的,而是着重讲解B+树这玩意,下面简单讲解下二叉树和红黑树
在上图中,这种结构的缺点比较明显,无论是二叉树和红黑树都会因为树的深度过深,而造成IO次数变多,IO次数多了就会影响读取数据的效率
实例图说明:
每个磁盘块,可以理解为存储固定大小的的值,每个节点占用一个磁盘块,一个节点上有两个升序排列的关键字,和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址,两个关键词划分成三个范围域对应三个指向子树的数据的范围,以根节点为例,关键字为16和34,p1指针指向子树的数据范围小于16,p2指针指向子树的数据范围为16-34,p3指针指向的子树的数据范围为大于34。
查询过程
B树的特点
缺点
将数据范围变为多个区间,区间越多,数据检索越快
之所以这么做是因为在数据库中页的大小是固定的,InnoDB 中页的默认大小是 16KB。如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的 IO 次数又会再次减少,数据查询的效率也会更快。另外,B+ 树的阶数是等于键值的数量的,如果我们的 B+ 树一个节点可以存储 1000 个键值,那么 3 层 B+ 树可以存储 1000×1000×1000=10 亿个数据。一般根节点是常驻内存的,所以一般我们查找 10 亿数据,只需要 2 次磁盘 IO。
虽然InnoDB和MyISAM存储引擎都是使用B+树,但是具体实现是有不同的,具体如下
InnoDB–B+树
上面3/5是根节点,包括分支节点是不存储数据的,只有对应的叶子节点才存储数据,上面淡黄色的是存储的值,深黄色的存储的是值,我们在建索引的时候是给每个列建索引,在上图中可以看出,3,5将数据划分为三块,当我们要查询3对应的数据时,只需要找到3,然后向下找一次即可找到3对应的数据,并直接得到3对应的数据,直接读取数据完事,这种方式效率比较高,并且这样我们树的深度不会特别深
注意
通过名字得到对应的主键索引,然后通过主键索引的B+树得到具体每行的值
MyISAM–B+树
MyISAM 中的 B+ 树索引实现与 InnoDB 中的略有不同。在 MyISAM 中,B+ 树索引的叶子节点并不存储数据,而是存储数据的文件地址。
关联
这里我们回顾一篇往期文章MySQL数据文件,这篇文章中有提到InnoDB和MyISAM存储引擎数据文件的区别,对这上面两种引擎B+数上的实现是相关联的
回表
关于回表这个专业术语,通过上面介绍InnoDB和MyISAM存储引擎中具体实现的B+树我们知道InnoDB的主键索引的B+树的子节点中是直接存储行的记录值,那么这个就不需要回表操作,但是一张表中不单只有主键索引,还有普通索引,如在上面讲到InnoDB中给name建普通索引,那么通过name维护的B+树索引得到name值对应的主键,然后再通过主键索引维护的B+树在查找到具体的行数据,那么这个过程就叫回表
索引覆盖
这个专业术语也需要结合索引的特性,这里写两条SQL,如下!
select * from t1 where name =‘tao’
select id from t1 where name =‘tao’
二者区别就是第一条查询所有字段,第二条只查询id,这二条语句的区别就再于是否会触发回表操作,第一条就会触发回表操作,是因为我们根据name这个字段的B+树只能得到对应name的id值,需要知道其他的字段还需要通过主键id维护的B+树回表进行查找,否则无法查找其他字段,而第二条SQL就只要id,那么无需查找其他字段,所以不会触发回表操作,那么个这个第二条不会触发回表操作的过程就叫做所以覆盖
最左匹配
这个是面试中的高频问点,索引的最左匹配原则!这个最左匹配原则是发生在建立多字段的组合索引是参数的,如我们有表t1字段有id,name,age,sex 当我们查询条件通常为name和age时,我们给以给name和age建立组合索引(name,age),这里最左匹配原则我们可以理解为(在我们查询地址的时候,必须先根据省查找,然后查询市,在查询区的顺序),我们写几条SQL来理解一下,如下
当前组合索引(name,age)
select * from t1 where name =‘tao’
select * from t1 where name =‘tao’ and age=10
select * from t1 where age=10
select * from t1 where age=10 and name =‘tao’
以上能用到索引的有第一条,第二条,第四条。第一条name能匹配到最左边的索引name所以是可以的,第二条,既能匹配到name也能匹配到age,第三条则是直接跨过了name那么违背了最左匹配原则的,所以不行,第四条,这个有人会质疑了,这里先查询的是age后查询的是name,顺序对不上呀,这里我们需要知道MySQL的逻辑架构,MySQL逻辑架构,MySQL逻辑架构中有一个优化器,这个优化器会帮我们优化SQL,所以这里优化后是name在前,age在后。这个我们可以创建索引使用explain看看。这里不单是在WHERE条件时会优化,在表关联的时候也会优化,如下
使用STRAIGHT_JOIN关键字强制关联顺序
这里为什么会有STRAIGHT_JOIN关键字,原因是在大部分情况下MySQL的优化器是能帮我们优化SQL的,但是少部分情况下还是需要根据我们自己的SQL执行,当我们需要SQL按照我们自己的意思执行的时候就可以使用STRAIGHT_JOIN了
索引下推(5.6之后才有的)
如我们有两个条件name、age,但是只有name做了索引,在正常查询的流程如下
那么采用索引下推后流程就是直接从存储引擎拉取数据的时候按照name和age做判断,将符合的结构返回给mysql的server
至于MySQL是否真的如我所说的使用B+树,我么可以看看官网!MySQL官网
这里B-树其实就是B树,而上面文章说到MySQL使用的则是B树的升级版也就是B+树了,还是信我说的话可以看看高新能MySQL这本书