MySQL聚集索引详解_mysql-索引详解

本文详细介绍了MySQL中的索引原理,包括索引的数据结构和选择,如二叉树、红黑树、哈希表、B-Tree和B+Tree。重点讲解了MySQL实际采用的B+Tree作为索引结构的原因,以及InnoDB存储引擎的聚集索引和非聚集索引的特点。此外,还讨论了主键、辅助索引、覆盖索引和联合索引的概念及其作用。
摘要由CSDN通过智能技术生成

直接起飞

1.什么是索引?

索引是帮助mysql高效获取数据的排好序的数据结构。

2.索引的数据结构?为什么选这种结构?

假设我们现在这里有一张表(以下情况都是innodb存储引擎):

id

number

1

33

2

18

3

14

4

22

5

57

6

8

7

20

8

72

9

51

如果mysql没有索引这种结构,那么我们如果查找number为51的这行记录,那么mysql就要从上往下扫描全表,找到number为51的这行记录需要9次;

二叉树?

如果mysql索引结构为二叉树呢?

我们要去查找51这个元素:

de22fa2ede1f885f0ccc3f5060b7fb59.png

我们只需要查找3次就能找到51这个元素,时间复杂度为O(3);

那么我们mysql索引用的就是二叉树结构吗?

肯定不是的,如果是二叉树,那么我把id这一列作为索引会是怎么样的情况:

假设我们现在要查找id为7的这一列:

fa35b155c52c4191001b066b0ad43668.png

这个时候二叉树已经是链表化了,我们查找7这个元素就需要找7次,时间复杂度为O(7);

二叉树对于连续自增的数据会转为链表化,不适合做这种数据的查找。我们排除这种数据结构。

红黑树?

假设mysql索引为红黑树,这个时候我们还是先去查找number为51的这一行:

df65ae9ee67234001a14f49b518de386.png

我们需要查找4次就能找到51这个元素,时间复杂度为O(4);

再看如果查找id为7的元素呢?

5e36a1839513bea2b9857ff88f5f5eb8.png

这次找id为7的元素,只找了4次,比二叉树次数少多了;

那么mysql用的是红黑树吗?我们来思考一个问题:

如果我数据库里面有几千万条数据,也就是说,id是自增的几千万个,那么这个红黑树高度是不是很高,查询元素时间复杂度为O(n);这显然是不符合我们mysql高数据量的时候查找;

hash表?

476e8ead8eafad4b4a06545f77f43708.png

查找id为7,只需要一次,很快,很棒,这也是mysql索引的一种;

但是,我们来想想这有什么缺陷:

1.hash冲突问题;

2.如果我想查找2

答案肯定是不行的,hash只适合做简单查询,但是它效率非常高,只需要去hash表中查找一次就能精确定位到数据,但是hash表只能做一次hash运算去查找元素,像前面的情况,就无法使用索引去查找元素了。

来验证一下,我们给test表加上hash索引:

c866d6b97711d2e023507f13d3132700.png

1f923aa4e5bdc529a9fdbaf7d265f1dc.png

查询一个money的区间:

904e155b3bfa22b6206fd96291b37d9a.png

直接走的全表扫描,并没有走索引;

B-Tree?

我们还是来查找money为51的这行数据:

81838c7d21498363a3851af6fa2d107f.png

我们可以看到,一颗高度为3的b tree上,我们去查找元素时间复杂度最多为O(3);我们去查找51也是查找3次,很好的解决了元素查找问题;

再看这棵树上面,叶子节点都是排好序的,但是需要去查找的话,还是需要从根节点开始查找,并没有完美解决hash表不能做的范围查找;(范围查找时间复杂度高)

那么mysql用的是b tree吗?mysql用的不是b tree,我们下面来看b+tree;

B+Tree

mysql索引使用的就是b+tree;为什么mysql会选用b+tree呢?我们来看b+tree的结构:

abd091e84924a7ccd4242fb53f1b76db.png

从结构上来看,b+tree多了冗余数据,叶子节点上面有指向下一个叶子节点的指针;

如果是范围查找,我查找到一个数据,那么根据叶子节点指针就能顺藤摸瓜找到这个范围能的数据,完美解决了hash表的范围查找;

b+tree跟b tree还有一个区别点是b+tree(数据库这行data)只放在了叶子节点;而b tree在第二行数据块上面也存有着 (数据库这行data),一个数据库只有16kb大小,容量有限,在有限容量下,b+tree的冗余设计要比b tree能存放更多的数据;

3.为什么选用InnoDb存储引擎

1.表数据文件本身就是按照b+tree组织的文件存储,主键索引上面包含了整行的全部数据,节省了磁盘空间;

2.聚集索引(主键索引)的叶子节点包含了整行数据;MyISam引擎文件和数据是非聚集的(索引文件myi和数据文件myd并不是在一个文件,这一点innodb都是存放在ibd文件);

3.innodb支持事务;

4.各种索引

4.1主键索引(聚集索引)

以主键数据作为索引列,叶子节点上包含了行所有的数据:

833d3099a06da1264ab4a126f376e067.png

4.2稀疏索引(辅助索引,非聚集索引)

以非主键列作为索引,叶子节点上面只有id,如果需要查询这行全部数据,需要去主键索引上面回表:

3c383b099ed83ed4c5c5a5289bca4eaf.png

4.3覆盖索引

所谓覆盖索引,其实上就是非主键索引,但是被称做覆盖索引是因为sql的查询项中只包含了索引列和id,不需要去主键索引回表,这样的操作就称为覆盖索引查询。

4.4联合索引

所谓的联合索引,其实就是由多个字段组成的辅助索引;符合最左前缀匹配规则(结合索引的有序性,就能明白为什么是最左前缀匹配原则;后面sql优化中会讲到这些):

29a052f6893f7b06ee912cc12cca08be.png

问题1:为什么非主键索引叶子节点存储的是主键?

可以节省磁盘存储空间,ibd文件会相对较小;

行数据做更改的时候并不影响辅助索引,只存储id的奥妙所在(更改不需要去维护索引);

问题2:为什么innodb存储引擎的表必须要建主键?并且推荐使用自增主键?

如果没有主键就无法维护ibd文件,innodb必须要有索引;如果建表的时候没有设置主键,innodb会维护一个隐藏列去作为主键索引;

自增索引插入的时候效率要比其他要高出很多;而且作为int或者long,比起uuid所占用字节是要少的多的,也就是说,上层荣誉节点可以放更多,下层叶子节点也可以放更多的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值