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

MySQL中的索引

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

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

主键索引

定义:唯一且不为空,简称主键,表中可以没有主键,但是最多只能有一个;

在Innodb中,会默认将主键索引设置为聚簇索引;

一般而言,主键索引的建立符合以下的原则:

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

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

普通索引(NORMAL)

定义:设置单个字段作为索引,没有任何限制,是我们使用最多的索引;

普通索引的查询,在innodb中其是非聚簇索引,索引它存在一个回表的过程,所以后期有个优化便是使用覆盖索引;

唯一索引(UNIQUE)

定义:设置单个字段作为索引,并且该索引不会重复,可以为null;

主要是对该索引字段进行唯一性限制。

组合索引

定义:设置多个字段作为索引;

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

以上是按照索引的使用类型来划分的;

按底层数据结构分可以分为2类:

  • B-Tree索引
  • hash索引

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

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

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

  1. 如果不符合最左匹配原则,那么无法进行匹配;
  2. 不能跳过索引中的列;我的理解是,假如我WHERE name = 'hyx' AND age = 18,在name字段上有一个普通索引,数据表中有很多个name为hyx的用户,这个时候不能直接跳过中间age != 18的列,而是要一个一个取出来,然后回表去查age,最后在判断是否为18,相当于必须扫描这些不正确的数据行。

    hash索引使用的底层数据结构为Hash表,等值匹配速度很快,但是范围遍历效率低。
  3. 一旦使用范围查询,那么其右边的所有列都无法走索引;我认为这也是最左匹配原则的体现;

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

Hash索引的特点:

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

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

建立高性能索引的策略

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

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

独立的列

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

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

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

使用前缀索引

我们都知道,现实中是存在例如邮箱等的具有相同后缀的数据的,所以我们肯定指定使用其前缀索引来减小和加快索引的查找,但是会降低选择性;

选择性是不重复的列 / 总数据列数的值,最好为1,我们可以使用COUNT()函数来计算其选择性,来选取与原来的选择性相差不大的情况;

使用覆盖索引避免回表

我们知道,如果在一个字段上面建立一个索引,那么索引的节点其实是存储了值,主键的,获取主键之后,再需要去主键所在的B+树进行查找,才能查找到具体数据。

而如果使用了覆盖索引,例如我们建立一个组合索引“email,phone”,当我们利用WHERE email = '843497509@qq.com'查找phone的时候,其实我们已经获取了phone的数据,所以MySQL不会进行回表操作,而是直接返回结果集。

利用索引进行排序

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

深入MySQL(三):MySQL的索引的应用的更多相关文章

  1. MySQL(三)

    MYSQL(三) 上一章给大家说的是数据库的视图,存储过程等等操作,这章主要讲索引,以及索引注意事项,如果想看前面的文章,url如下: MYSQL入门全套(第一部) MYSQL入门全套(第二部) 索引 ...

  2. mysql btree与hash索引的适用场景和限制

    btree索引: 如果没有特别指明类型,多半说的就是btree索引,它使用btree数据结构来存储数据,大多数mysql引擎都支持这种索引,archive引擎是一个例外,5.1之前这个引擎不支持任何索 ...

  3. 【MySQL】MySQL索引背后的之使用策略及优化【转】

    转自:http://database.ctocio.com.cn/353/11664853.shtml 另外很不错的对于索引及索引优化的文章: http://www.cnblogs.com/magia ...

  4. MySQL源码:索引相关的数据结构

    http://www.orczhou.com/index.php/2012/11/mysql-source-code-data-structure-about-index/ 本文将尝试介绍MySQL索 ...

  5. mysql建立、删除索引及使用

    同步发布:http://www.yuanrengu.com/index.php/2017-01-13.html 一.索引的作用 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少 ...

  6. MySQL中的联合索引学习教程

    MySQL中的联合索引学习教程 这篇文章主要介绍了MySQL中的联合索引学习教程,其中谈到了联合索引对排序的优化等知识点,需要的朋友可以参考下   联合索引又叫复合索引.对于复合索引:Mysql从左到 ...

  7. MySQL性能调优——索引详解与索引的优化

    --索引优化,可以说是数据库相关优化.理解尤其是查询优化中最常用的优化手段之一.所以,只有深入索引的实现原理.存储方式.不同索引间区别,才能设计或使用最优的索引,最大幅度的提升查询效率! 一.BTre ...

  8. SQL优化 MySQL版 - B树索引详讲

    SQL优化 MySQL版  - -B树索引详讲 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太 ...

  9. mysql 最左匹配 联合索引

    mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先,如: 如果有一个2列的索引(col1,col2),则已经对(col1).(col1,col2)上建立了索引:如果有一个3列索引(col1 ...

  10. 【面试】MySQL的事务和索引

    MySQL事务 MySQL事务主要用于处理操作量大,复杂度高的数据. 比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这些数据库操作 ...

随机推荐

  1. 《剑指offer》面试题52. 两个链表的第一个公共节点

    问题描述 输入两个链表,找出它们的第一个公共节点. 如下面的两个链表: 在节点 c1 开始相交. 示例 1: 输入:intersectVal = 8, listA = [4,1,8,4,5], lis ...

  2. unity3d百度语音合成mp3流转换byte[]失败

    using (Stream stream = response.GetResponseStream())         {             buffer2 = new byte[stream ...

  3. 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引

    系列背景 在进入微服务的实践系列之前,我们一起来学习和实践一下.NET应用开发生态中一些比较重要的技术,这个系列就是关于GraphQL在.NET 6应用中的实现. 系列导航 使用Hot Chocola ...

  4. VAE变分自编码器

    我在学习VAE的时候遇到了很多问题,很多博客写的不太好理解,因此将很多内容重新进行了整合. 我自己的学习路线是先学EM算法再看的变分推断,最后学VAE,自我感觉这个线路比较好理解. 一.首先我们来宏观 ...

  5. django_url配置

    前言 我们在浏览器访问一个网页是通过url地址去访问的,django管理url配置是在urls.py文件.当一个页面数据很多时候,通过会有翻页的情况,那么页数是不固定的,如:page=1.也就是url ...

  6. 加深对AQS原理的理解示例二:自己设计一个同步工具,同一时刻最多只有两个线程能访问,超过线程将被阻塞

    /** *@Desc 设计一个同步工具,同一时刻最多只有两个线程能访问,超过线程将被阻塞<br> * 思路分析: * 1.共享锁 两个线程及以内能成功获取到锁 * 2. *@Author ...

  7. linux文件时间详细说明

    目录 一:文件时间信息 2 文件时间详细说明 一:文件时间信息 1 文件时间信息分类: 三种时间信息 文件修改时间: mtime 属性修改时间: ctime 文件访问时间: atime 2 查看文件时 ...

  8. python06day

    Now代码1005行 回顾 字典的初识 查询速度快,{'name':'tangdaren'},存储大量关联型数据 键:int.str(bool tuple不常用)不可变的数据类型 值:任意数据类型 3 ...

  9. 学习Java第6天

    今天所做的工作: 1.完成学生信息管理系统样卷 2.核心技术接口继承,多态 明天工作安排: 1.类的高级特性(Java类包) 2.异常处理 今天做一个小小的总结,Java程序是完全面向对象的,它的所有 ...

  10. uni微信小程序优化,多个分包在用的公共代码该放在哪?

    公共的代码包括公用的vue组件和js代码,从维护性的角度来说应该放到主包才对, 但是主包有大小限制,如果把2个分包都在用的代码放到主包里面那2M很快就满了. 所以该放在哪?我的方案是从维护的角度放在主 ...