MySQL索引原理

什么是索引?

官方定义:索引(Index)是帮助MySQL高效获取数据的数据结构。

索引结构设计

为什么要有索引?数据结构的选择,无非就是时间复杂度的选择。本质上是查找算法,即通过最少的I/O次数,便能检索到目标数据。

索引数据结构的演进:二叉树 --> 二叉查找树 --> 平衡二叉查找树 --> 多路平衡查找树(B Tree) --> 加强版多路平衡查找树(B+ Tree)

二叉查找树

二叉查找树:基于二叉树,加入了左子数必须小于父节点,右子数必须大于父节点的规则。但是会存在极端情况--斜树(左斜或者右斜),这会导致树的深度过深,树的深度越深意味着I/O次数越多。

平衡二叉查找树

平衡二叉查找树:基于二叉查找树,加入了节点旋转的规则。通过旋转,减少数的深度。但是每个节点只能有一个关键字,效率也并不是很高。

多路平衡查找树(B Tree)

多路平衡查找树(B Tree):基于平衡二叉查找树,在节点中可以存储多个关键字,意味着分叉数越多,也就降低了树的深度,从而减少I/O的次数。

B Tree特点:分叉树(路数)永远比关键字数多1。

加强版多路平衡查找树(B+ Tree)

 B+树相比B树的优化:

1.B树的路数和关键字的个数关系不再成立,数据检索规则采用的是左闭合区间,路数和关键词数为1比1.

2.B+树的根节点和枝节点都不会存储数据,只有叶子节点才会存储数据,并且每个叶子节点都会增加一个指针指向相邻的叶子节点,形成一个有序链表结构。

3.B+ 树关键字的搜索采用左闭合区间。

4.B+ 树的根节点和枝节点不存储数据,只有叶子节点才存储数据内容或者是内容的地址。而在B树中,如果命中了节点,则会直接返回数据(因为关键字和数据存储在一起)。

5.B+树中,叶子节点不会保存子节点的引用。

MySQL为何选择B+树?

1.扫库、扫表能力更强。(当需要对全表进行扫描时,只需要遍历叶子节点即可,不需要遍历整个B+树)

2.B+树的读写能力更强。(一个节点可以保存更多的关键字,减少I/O次数)

3.排序能力更强。(叶子节点是有序的链表结构)

4.效率更加稳定。(永远是在叶子节点获取数据,I/O次数是稳定的)


MyISAM引擎的索引实现

在MyISAM里面,另外有两个文件:

一个是.MYD文件,D代表Data,是MyISAM的数据文件,存放数据记录,比 如我们的user_myisam表的所有的表数据。
一个是.MYI文件,I代表Index,是MyISAM的索引文件,存放索引,比如我 们在id字段上面创建了一个主键索引,那么主键索引就是在这个索引文件里面。
一个索引就会有一棵B+Tree,所有的B+Tree都在这个MYI文件里面。
从MyISAM引擎中索引的实现来看,由于索引文件和数据文件是分离的,叶 子节点存储的是数据文件对应的磁盘地址,从索引文件.MYI中找到键值后, 会到数据文件.MYD中获取相应的数据记录。
在MyISAM引擎中,主键索引和辅助索引在结构上没有任何区别,只是主键 索引要求key是唯一的,而辅助索引的key允许重复!

InnoDB的索引实现

在InnoDB中,只有一个ibd文件,里面包含索引和数据。 在B + Tree中的叶子节点存储了索引对应的数据行,所以我们称 InnoDB中索引即数据、数据即索引。


聚簇索引和非聚簇索引

聚簇索引:就是指索引键值的逻辑顺序和表数据行的物理存储顺序一致。只有聚簇索引才会在叶子节点缓存表中的数据。

在InnoDB中,组织数据的方式就是用聚簇索引组织表(Clustered Index Organize Table),所以一张表创建了主键索引,那么这个主键索引就是聚 集索引。

非聚簇索引:除了主键索引以外,其他索引均属于非聚簇索引,非聚簇索引的叶子节点不会存储表数据

 从上面这个图可以看到,真正的数据仍然是保存到主键索引的叶子节点(这也就是为什么InnoDB表必须要有主键的原因),而辅助索引的叶子节点的数据区保存的是主键索引的关键字的值(非主键索引叶子节点的逻辑顺序和磁盘顺序不一致)。

MyISAM和InnoDB两种引擎索引区别


索引创建建议

1.在用于where判断、order排序、join on 、group by 的字段上创建索引。

2.索引不易太多。

3.对于过长的字段,建议建立前缀索引。

4.区分度低的字段,不要建索引。(离散度太低,导致扫描行数过多)

5.频繁更新的值,不要作为主键或者索引。(B+树的平衡导致 页分裂,影响效率)

6.随机无序的值,不建议作为索引,例如身份证、UUID。(无序,页分裂)

7.组合索引把离散度高(区分度高)的值放在前面。

8.创建复合索引,而不是修改单列索引。

索引失效

1.索引列上使用函数(sum、count、avg等)、表达式。

ps:https://www.runoob.com/mysql/mysql-functions.html

2.字符串不加引号,出现隐式类型转换。(出现隐式转换,会导致全表扫描)

eg:

3.like条件中前面带%。(最左匹配原则)

4.负向查询。

Not Like:

 != (<>)和NOT IN 在某些情况下可以:

 因为主键索引是有序的,因此只需要从1之后开始读取即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值