mysql-索引
Posted Zheng"Rui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql-索引相关的知识,希望对你有一定的参考价值。
索引
一、索引的作用
索引是mysql的存储引擎为了快速找到记录而设置的一种数据结构,索引对于良好的性能非常关键,尤其是当数据量很大的时候,能够明显提升查找的性能。mysql中的索引工作原理和一本书的索引是一样的,我们想要在书中找到一个主题,需要先查找索引找到对应的页码。在mysql中,存储引擎使用了类似的方法实现索引,首先在索引中找到对应的对应的值,然后根据索引值找到对应的数据行。
二、索引的分类
索引有很多种类型,可以为不同的场景提供高性能的服务。在mysql中索引是由存储引擎层实现的,而不是由服务层,这样实现可以让mysql更加的灵活,针对不同的业务场景,选择不同的存储引擎,每种存储引擎有自己的索引实现,能够更好的应对不同的业务场景。
2.1 B-Tree 索引
大多数时候,说的mysql索引指的都是B-Tree索引,它使用B-Tree或者其变种作为数据结构来组织索引和数据,在InnoDB和MyISAM中使用B+Tree来存储索引。在InnoDB的叶子结点中使用主键来引用数据,MyISAM中使用数据的物理存储位置来引用数据。
在B-Tree中,所有的值都是按顺序存储的,并且每一个叶子节点到根结点的距离相同,B-Tree索引之所以快,就是因为它不在需要扫描所有的数据,而只需要从根结点出发,通过比较结点页的值和要查找的值可以找到合适的指针进入下一层,这些指针其实就定义了子结点页值的上下限。
B-Tree是按照顺序存放的,所以非常适合做范围查找,当有多个索引列的时候,会按照定义索引列的顺序,进行排序。
2.1.1 B-Tree可以使用的场景
1.全值扫描,也就是用到了定义的所有索引列,并且都使用精确匹配。
2.最左前缀索引列匹配:如果定义了以a,b,c三个字段为组合索引,那么查询条件中,使用到a,或者a,b,或者a,b,c都会走索引。但是c,或者b,c就不会走索引
3.最左前缀匹配:当使用模糊查询的时候,如果只知道索引的前几个字符,同样可以进行查询,比如定义a字段为索引,那么可以使用 a=abc%,来作为条件,也会走索引。
4.精确匹配索引加模糊匹配:当定义a,b,c三个字段为组合索引时,可以使用a作用精确匹配,b为模糊匹配,同样会走索引,但是此时c这个字段就不会走索引了,需要查找到结果之后,逐个匹配。
5.覆盖索引
当查询的结果就是使用到的索引的时候,会进行覆盖索引,不需要回表操作。
2.1.2 B-Tree索引的限制
1.刚才说了B-Tree的最左匹配,这是B-Tree的一大限制,因为如果我定义了a,b,c为组合索引,但是查询的时候,只用到了c,是没有办法走索引的,只能重新建立索引。
2.因为最左匹配,查询的时候,同样不能中间跳过某个字段,比如使用a,c做查询,跳过b,这样的话,只有a会走索引,c会对结果进行逐个判断。
3.刚才也有提到范围查询,范围查询可以走索引,但是范围查询之后的字段就没有办法走索引了,比如,a字段使用范围索引,那么b,c字段就没有办法走索引了。
总结所以,在B-Tree索引中,索引声明的顺序十分关键,在进行索引优化的时候,不同顺序的索引,会带来不同的性能。
2.2 哈希索引
哈希索引是基于哈希表实现的,哈希索引必须要精确匹配到所有的索引列才会生效,哈希索引其实就是对每一行数据,对所有的索引列取hash值,得到哈希码,然后将哈希值和对应的数据行指针存在哈希表中,在Memory存储引擎中,哈希索引是默认的索引结构,Memory支持非唯一索引,也就是当索引列的值相同而发生哈希冲突的时候,会以链表的形式来组织数据行,这样,查询的时候,进行遍历即可。
哈希索引在某些情况下的性能非常好,能够达到o(1)时间复杂度的查询,并且索引本身只需要存储对应的哈希值,结构比较紧凑,占用的空间小。
但是哈希索引也有限制:
2.2.1 哈希索引的限制
1.哈希索引中存放的是索引对应的哈希码和数据行指针,没有存储索引值,所以没有办法进行覆盖索引,必须通过指针找到数据行。
2.虽然在索引中,哈希码是按照顺序存放的,但是对应的数据行并不是按照顺序存放的,所以没有办法进行范围查询。也没有办法进行排序。
3.因为哈希码是根据所有的索引列计算得来的,所以不支持部分索引匹配,必须要在查询的时候用到所有的索引。
4.当给一个区分度不高的字段建立哈希索引之后,会出现很多冲突,导致效率迅速降低,并且此时想要对数据行进行操作的时候,比如想要删除一行数据的时候,就必须删除该行数据对应的索引,因为区分度不高,所以需要进行遍历很多行数据,效率不高。
2.2.2 Innodb的自适应哈希
在Innodb存储引擎中,存在自适应哈希算法,也就是当Innodb发现我们非常频繁的使用某个查询条件的时候,会给这个字段,在B-Tree的基础上增加哈希索引,这样能够进行更快速的查询。
2.2.3 自定义哈希
我们也可以自己实现一个哈希索引,当然,和哈希索引不同,我们借助B-Tree来实现,在Innodb中,我们有时候需要进行查询很长的字符串,这种字符串的查询,即使有索引,效率也不高,所以我们可以建立自定义索引,首先需要自己定义一个哈希函数,然后在插入数据的时候,将这个很长的字符串进行哈希之后,存储一个新的字段,然后在哈希字段上建立索引,之后查询的时候,只需要查询条件写一个字符串的精确匹配,一个哈希码的精确匹配,此时哈希码的匹配会走B-Tree索引,而且哈希码比较短,所以很快,剩下的数据,是哈希冲突的数据,在使用遍历的方式进行查找即可。
以上是关于mysql-索引的主要内容,如果未能解决你的问题,请参考以下文章