深入MySQL(三):MySQL的索引的应用

深入MySQL(三):MySQL的索引的应用,第1张

深入MySQL(三):MySQL的索引的应用

在MySQL的优化中,索引的作用绝对算是一个大头,很多时候索引使用得当可以使得一个查询的效率提高几个数量级,同时它还具有自动排序等功能。所以如果是深入MySQL,那么索引绝对是其中重要的一部分。

MySQL中的索引

MySQL中的索引按类型分大致可以分为5类:

主键索引普通索引唯一索引文本索引组合索引 主键索引

定义:唯一且不为空,简称主键,表中可以没有主键,但是最多只能有一个;
在Innodb中,会默认将主键索引设置为聚簇索引;
一般而言,主键索引的建立符合以下的原则:

    与业务无关的自增属性作为主键;不选取可以动态变化的属性,例如时间戳;字段值不进行更新;

用户量较小的情况下,一般用自增序列即可满足条件,但是在一些情况下,主键的选择就不只是简单的自增属性了,后续会专门出一篇博客重新讲述分布式唯一ID的生成算法。

普通索引(NORMAL)

定义:设置单个字段作为索引,没有任何限制,是我们使用最多的索引;
普通索引的查询,在innodb中其是非聚簇索引,索引它存在一个回表的过程,所以后期有个优化便是使用覆盖索引;

唯一索引(UNIQUE)

定义:设置单个字段作为索引,并且该索引不会重复,可以为null;
主要是对该索引字段进行唯一性限制。

组合索引

定义:设置多个字段作为索引;
将多个字段作为一个索引,索引选取的字段的顺序很重要,遵循最左匹配原则。

以上是按照索引的使用类型来划分的;
按底层数据结构分可以分为2类:

B-Tree索引hash索引

Innodb中默认使用的便是B-Tree索引,其底层数据结构是B+树,对以下类型的查询有效:

    全值匹配:指的是和索引中的所有列进行匹配,即例如WHERe name = ‘hyx’ AND age = 18的查询;匹配最左前缀:即组合索引中的使用前面的字段进行匹配;匹配列前缀:LIKE的用法也是复合最左匹配原则的;匹配范围值:B-Tree索引会按照大小将数据排序存放;精确匹配某一列并范围匹配另外一列;只访问索引的查询;

但是B-Tree索引也有缺点:

    如果不符合最左匹配原则,那么无法进行匹配;不能跳过索引中的列;我的理解是,假如我WHERe name = ‘hyx’ AND age = 18,在name字段上有一个普通索引,数据表中有很多个name为hyx的用户,这个时候不能直接跳过中间age != 18的列,而是要一个一个取出来,然后回表去查age,最后在判断是否为18,相当于必须扫描这些不正确的数据行。
    hash索引使用的底层数据结构为Hash表,等值匹配速度很快,但是范围遍历效率低。一旦使用范围查询,那么其右边的所有列都无法走索引;我认为这也是最左匹配原则的体现;

大家可以看到,B-Tree索引的很多运用场景都与最左匹配原则有关,所以大家写查询的时候一定记住思考最左匹配原则,同时通过EXPLAIN来查看语句的执行计划来优化索引;

Hash索引的特点:

    哈希索引只包含哈希值和行指针,而不存储字段值,所以无法使用覆盖索引的做法避免读取行。不会自动进行排序;不支持索引列匹配,比如一个数据列(A,B)上建立索引,它始终是使用索引列的全部内容进行计算哈希值的,所以如果查询只含有数据列A,无法使用索引;只支持等值比较;访问速度极快,除非hash冲突很多;hash冲突很多的时候,维护的代价也会提高。

Hash索引的话,只适用于某些特定的场合。

建立高性能索引的策略

按照经验来说,其实我们使用WHERe的字段,就可以建立索引;但是作为技术人员,我们应该严谨的研究什么时候添加索引。我们这里暂时都只对B-Tree索引进行讨论,先来看B-Tree索引带来的好处:

    索引大大减少了扫描的行数;索引可以避免排序和临时表;索引可以将随机IO变为顺序IO;
独立的列

独立的列主要代表两个方面:

    索引列不能是表达式的一部分;索引列不能是函数的参数;

其实我觉得很好理解,因为以上的两种情况,都要对列进行计算,相当于就不是原来的列了,所以就无法使用索引;

使用前缀索引

我们都知道,现实中是存在例如邮箱等的具有相同后缀的数据的,所以我们肯定指定使用其前缀索引来减小和加快索引的查找,但是会降低选择性;
选择性是不重复的列 / 总数据列数的值,最好为1,我们可以使用COUNT()函数来计算其选择性,来选取与原来的选择性相差不大的情况;

使用覆盖索引避免回表

我们知道,如果在一个字段上面建立一个索引,那么索引的节点其实是存储了值,主键的,获取主键之后,再需要去主键所在的B+树进行查找,才能查找到具体数据。
而如果使用了覆盖索引,例如我们建立一个组合索引“email,phone”,当我们利用WHERe email = '[email protected]’查找phone的时候,其实我们已经获取了phone的数据,所以MySQL不会进行回表 *** 作,而是直接返回结果集。

利用索引进行排序

MySQL的排序是一个很麻烦很复杂很耗性能的一个过程,甚至会进行大量的磁盘IO,所以如果某一个字段需要经常性的排序,在B+树中,会自动根据B+树的节点值进行排序,所以我们就会省略这个字段的排序过程。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5719416.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存