mysql索引数据结构

在讲解mysql索引之前什么是索引,mysql索引就是一个排好序数据结构
排好序我们先姑且不论,数据结构我们应该都很清除,我们需要先知道常用于索引的数据结构有那些?

  • 二叉树
  • 红黑树
  • B-Tree(b树)
  • B+Tree(b+树)
    这里我们应该都知道mysql既不是使用二叉树也不是使用红黑树,而是使用的B+Tree。
    下面我们逐一分析,为什么mysql使用b+tree而不使用另外三种。
    附上一个数据结构演示网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

二叉树

首先什么是二叉树?二叉树是一个树形结构,且右子叶的数据大于父节点,左子叶的数据小于父节点,如下图所示:
在这里插入图片描述
那么二叉树的问题是什么呢?mysql中我们经常使用自增的主键组织索引,我们可以模拟以下自增主键插入索引会是什么效果,如下图:
在这里插入图片描述
我们发现二叉树变成了链表,那如果我们按照这个索引查找数据岂不是跟没有走索引一样,我们有多少条数据就会查找多少次,相当于没有索引

红黑树

我们在看红黑树,红黑树又叫二叉平衡树,这里直接看图:在这里插入图片描述
其实红黑树的问题我们不是很主观的能够看出来,这是因为我们插入的数量少,假设我们有上千万的数据,可以想象以下,红黑树的层级会不会很高,那查找的时候我们就需要查找很多的层级,这里我们就可以得出一个结论mysql索引怎么才能查找最少的层级就可以定位到我们的目标数据,那就是b-tree

B树(B-Tree)

B树属于多叉树又名平衡多路查找树,每一子节点可以存在多个元素,每一个节点上都携带了指向下一子节点的指针,这种结构可以减少树的层级,如下图

在这里插入图片描述
但是它仍有不足之处,比如每个节点元素上都必须包含对应的数据地址,这样每一节点能够存放的数据就会变少,层级也就会变多.

B+Tree

B+Tree是B树的一个升级,B+跟B树不同B+树的非叶子节点不保存关键字记录的指针,只进行数据索引,这样使得B+树每个非叶子节点所能保存的关键字大大增加;这样直接导致我们可以以更少的层级存储大量的索引;
B+树叶子节点保存了父节点的所有关键字记录的指针,所有数据地址必须要到叶子节点才能获取到。所以每次数据查询的次数都一样;
B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针。
如下图:

在这里插入图片描述注意上图叶子节点中的指针是单向的,但是mysql对b+树进行了优化,是一个双向的指针

什么是聚集索引和非聚集索引

mysql常用的存储引擎有myisam和innodb. 其实可以通过观察数据表的文件就可以知道,有兴趣的可以查看data目录下对应表的文件,

myisam一个表有三个文件分别是.frm .myd .myi他们分别对应表结构,表数据,表索引,在myisam存储引擎中数据文件和索引文件是分开存储的,在myi文件中存储的是一个b+tree结构的索引(正常是按照主键组织的),然后索引的叶子节点会存放对应数据行在.myd文件中的磁盘地址,然后再通过磁盘地址到myd文件中定位到查询的数据行。

innodb一个表有两个文件分别是.frm .ibd分别对应表结构,表数据,注意innodb引擎的索引也是放在ibd文件中的,其实.ibd文件中存储就是表数据,只不过表数据是按照b+tree数据结构组织的,而该数据结构默认也是按照主键组织的,就像我们上图中看到的b+tree的数据结构,只不过在innodb中表的数据是直接存储在叶子节点上的。我们可以直接通过索引定位到数据行,而不再需要像myisamy存储引擎一样再到myd文件中查找数据。

而这种像myisam存储引擎索引和数据时分开存储的我们就叫做非聚集索引,而像innodb索引和数据时存储到一起的我们称为聚集索引
如下图,是一个主键索引也是聚集索引

在这里插入图片描述
如下图,是一个二级索引也是非聚集索引,叶子节点存的是构建聚集索引的索引ID
在这里插入图片描述

为什么mysql推荐我们在表中创建主键索引

mysql的表在创建的时候如果我们创建了主键索引,那么表在组织b+tree树索引时会直接采用我们创建的主键进行构建索引也是聚集索引,但是我们有时候并不创建主键,那mysql是怎么组织b+tree的呢?其实mysql会先查找没有重复值的列用于构建聚集索引,如果还没有满足条件mysql就会默认维护一个rowid用来构建聚集索引。
这里需要注意的是,我们的innodb引擎的表必须有一个聚集索引,而当我们创建二级索引也就是非主键索引时,二级索引的叶子节点存的是聚集索引的主键或者是rowid,这样当我们通过二级索引查找数据时先通过二级索引定位到叶子节点上的主键,然后再通过主键到聚集索引上去定位查找的数据行

为什么mysql推荐主键是自增的?

我们知道mysql是通过b+tree数组织索引的,而b+tree的是一个有序的数据结构,当我们不是以自增的顺序插入数据时就会造成b+tree结构的重新平衡和排序,如果我们直接插入的时候就是有序的,那mysql就不需要在去排序叶子节点,直接在后面新增一个节点。

复合索引的底层存储结构是什么样的

其实复合索引的底层存储结构和非符合索引是一样的,比如下面有一个三列的复合索引
key index_name (name,age,position) using btree;
那么底层是怎么组织的呢?首先我们之前已经讲了索引是一个排好序的数据结构,那首先肯定是先要排好序,mysql会先按照name列进行排序,如果name相同则再按照age列排序,如果还相同则按照position排序,如下图所示:
在这里插入图片描述
注意上图,其实是一个复合主键索引,可以看到我们的叶子节点是直接存的数据,而不是主键ID

最左列前缀匹配原则

知道了复合索引之后,那我们就可以明白为什么mysql有最左列前缀匹配原则了,例如下面的查询语句:
select * from employees where age=30 and position=‘dev’;
我们知道上面这条语句是无法使用我们创建的符合索引的,因为age在单个节点中是排好序的,但是在全局来说不是排好序的,比如age=30在第一个叶子节点是排好序的,但是在第三个叶子节点同样出现了age=30的数据,那么就会出现全表扫描的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值