我们在面试时,经常会被问到有关索引的知识,什么是索引?为什么索引可以加快数据查询?如何选择创建索引?索引的最左匹配原则是什么?等等,针对这些问题,你都可以在本篇博文中,找到你要想的答案。
1.索引的作用
简单来说,索引就可以帮助我们快速查找数据。那为什么索引可以帮助我们快速查找数据呢?首先我们要了解,MySql中,数据都是存储在页中的,在InnoDB中一个页的大小是16KB,数据页的结构如图所示:
那么索引就相当于为什么生成了一个目录,让我们可以快速定位我们的数据在哪个页上,而不用去一条一条数据的去找。
2.索引的底层实现
索引模型主要有三种:哈希表、有序数组,搜索树。
针对这三种模型,来做一个比较:
(1)哈希表:哈希是一种key—value的存储数据结构,我们在存储数据时,会将每个索引进行哈希算法运算,得到其哈希值来作为key,所以当我们进行数据查询的时候这个时间复杂度只是O(1),但这是理想的状态,因为在进行哈希运算时,可能多个值对应同一个哈希值,在再个哈希值后要加一个链表来存储相同哈希值的key,然后再通过链表遍历得到我们的数据;因为通过哈希算法进行转换是不规律的,所以使用哈希结构是,增加数据快,但在做区间查询的时候回慢,哈希机构只用于只做等值查询的表使用。
(2)有序数组:按照索引进行递增排序,是有规律的数据结构。所以在范围查询中很很快,它的查询复杂度为O(log(N)),带因为是有序排序,在插入一个新的数据时,要去和以前存在的数据进行比较,来确定插入的位置,所以插入速度慢,因此有序数组结构使用在一些不做改变的表上。
(3)二叉搜索树:这个数的特点就是父节点的大小,在两个子节点的值中间,并且左节点的值大于右节点的值。它的查询复杂度为O(log(N)),所以查询速度优越,但是在插入数据时,需要维护我们树的结构,所以插入数据慢。
那么MySql中主要是什么什么结构呢?已InnoDB存储引擎来说,它使用的是B+树结构!首先为什么不适用哈希的结构,因为在大数据量的情况下,多个数据会被分给同一个哈希值,这样就失去了哈希结构的有点;其次有序数组在插入数据时过慢也被舍弃,而如果使用二叉树,又因为节点太多,需要多次进行多磁盘来拿到我们的节点数据,这样大大降低我们的操作速度,所以我们通过增加分支来较少节点的存在,从而减少从磁盘中来获取我们的数据,加快查询速度。
3.为什么不能滥用索引
有的小伙伴会问,既然索引可以加快我们的查询速度,那在表中每个字段加上索引,那样查询起来,速度不就飞快了!当我们在创建一个索引的时候不能单单只考虑表的查询速度,还要考虑表的更新速度。已InnoDB引擎为例,在表的字段上每新建一个索引,都有新建一个索引的B+树,这个B+树就会占用我们的内存空间,而且当我们更新数据的时候,B+树的结构也会发生改变,这个时候就会降低我们的性能。当我们在插入数据和删除数据的时候可能会发生数据页的分裂和页合并,就比如我们在插入一条新的数据时,刚好占用了这个页的全部空间,那么多余出来的数据就无法存放在这个数据页上,从而新增一个数据页,这个过程就是页分裂;同理当我们删除数据的时候就会发生页合并。当发生页分裂和页合并时,就需要维护我们的索引树,所以在插入和删除数据时,需要很多性能来维护我们的索引树结构,降低性能。
4.聚合索引和非聚合索引的区别
聚合索引——就是以主键来创建索引。
非聚合索引——就是以非主键的字段来创建的索引。
聚合索引和非聚合索引的主要区别就是,他们的子节点上存储的数据不同,聚合索引的子节点直接存储着是这个数据,而非聚合索引索引的子节点存储的是聚合索引的值,所以当使用非聚合索引会经历回表操作——通过拿到的聚合索引再去查找一次数据,称之为回表。
举个例子有一张表T有a,b两个索引,其中a是聚合索引,b是非聚合索引,那么当只想下面这个语句的操作流程是怎么呢?
//语句1
select * from T where a = 1
//语句2
select * from T where b = hu
语句1的执行流程:通过a索引拿到数据返回,流程结束。
语句2的执行流程:1.通过b索引的查询,拿到这条记录的主键;2,在通过主键去索引a中查询,得到数据返回,流程结束。
所以能使用聚合索引的性能是优于非聚合索引的。那么有没有什么办法解决这个回表操作呢?当然是有的,就是我们要说的覆盖索引。
什么是覆盖索引:就是放我们的查询结果的返回值只有主键和索引值值,就不需要就行回表操作,就是覆盖索引。比如现在有一张表id是主键,我们在username能添加一个索引,那当我们执行下面这个语句时,就不会进行回表查询:
select id,username from T where username = hu
5.索引的最左匹配原则
有的时候我们在写,查询语句的时候,明明已经在某个字段上加了索引,但在查询的时候并没有走索引,这是为什么呢?
这里就要说到索引的最左匹配原则,当我们定义一个组合索引(a,b),那么当我们进行下面两个语句进行查询
//语句1
select * from T where a = 1
//语句2
select * from T where b = 1
其中语句1会走这个(a,b)组合索引,而语句2不会走,这就是最左匹配原则。所以当我们在创建组合索引的时候,如何安排组合索引的顺序也是非常重要的。最左匹配原则还会针对模糊查询有效,还是(a,b)组合索引,下面两个sql语句:
//语句1
select * from T where a like '胡%'
//语句2
select * from T where a like '%胡'
这个时候语句1是走索引而语句2是不走索引的。
这篇文章就到这里,感兴趣的小伙伴,可关注本专栏,你的关注就是我更新的最大动力MySql专栏
---------------------
作者:呆东
来源:CSDN
原文:https://blog.csdn.net/huxiaodong1994/article/details/85002211
版权声明:本文为博主原创文章,转载请附上博文链接!