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索引,而且哈希码比较短,所以很快,剩下的数据,是哈希冲突的数据,在使用遍历的方式进行查找即可。
三、索引的优点
索引可以让服务器扫描更少的数据,更快的定位到要查找的数据行。但是,这并不是索引的唯一优点,根据上文描述,不同的索引,根据实现方式的不同,也能够带来一些附加效果。
比如,在B-Tree索引中,因为B-Tree是将值按顺序存放的,所以可以支持mysql做order by和group by等操作。并且,因为索引中存放了实际的列值,所以某些查询可以根据索引直接返回结果。
总结如下:
1.索引大大减少了服务器要扫描的数据量。
2.索引可以帮助服务器避免排序和建立临时表
3.索引可以将随机IO变为顺序IO
四、索引是最好的解决方案吗?
索引并不是在任何情况下都能优化查询。只有当我们建立索引带来的收益大于我们维护索引需要花费的成本的时候,索引才是有效的。在小型表中,直接使用简单的全表扫描反而效率更高。索引适合于中到到大型的数据表。对于特大型的表,维护索引带来的代价也会随之增加,这时候可以考虑分区技术。
以上是关于mysql-索引的主要内容,如果未能解决你的问题,请参考以下文章