14@MySQL索引原理与慢查询优化

索引原理与慢查询优化

探索索引的原理

1、为何索引叫key
2、索引是如何加速查询的,它的原理是啥?
  索引模型/结构从二叉树-》平衡二叉树-》b树最后到b+树,每种树到底有什么问题最终演变成到了b+树
3、为何b+树不仅能够加速等值查询,还能加速范围查询
4、什么是聚集索引,什么是辅助索引
5、什么情况下叫覆盖了索引
6、什么情况下叫回表操作
7、什么是联合索引,最左前缀匹配原则
8、索引下推,查询优化
9、如何正确使用索引?

一、索引介绍

1、索引是什么

索引是存储引擎中一种数据结构,或者说数据的组织方式,又称之为键key,是存储引擎用于快速找到记录的一种数据结构
索引是 MySQL 数据库中的重要对象之一,用于快速找出某个列中有某一特定值的行

#MySQL官方对索引的定义:
    索引(index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。简单理解为“排好序的快速查找数据结构”


#详解:
     数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构,就是索引


     数据建立索引就好比是为书建目录,或者说是为字典创建音序表,如果要查某个字,如果不使用音序
表,则需要从几百页中逐页去查

2、为何要使索引

索引优化应该是对查询性能优化最有效的手段了,索引能够轻易将查询性能提高好几个数量级

    一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的、也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然
是重中之重,说起加速查询,就不得不提到索引了。

3、如何正确看待索引

#索引的正确使用
   索引是应用程序设计和开发的一个重要方面。若索引太多,应用程序的性能可能会受到影响。而索引太少,对查询性能又会产生影响,要找到一个平衡点,这对应用程序的性能至关重要。
   一些开发人员总是在事后才想起添加索引----我一直认为,这源于一种错误的开发模式。如果知道数据的使用,从一开始就应该在需要处添加索引。开发人员往往对数据库的使用停留在应用的层面,比如编写SQL语句、存储过程之类,他们甚至可能不知道索引的存在,或认为事后让相关DBA加上即可。DBA往往不够了解业务的数据流,而添加索引需要通过监控大量的SQL语句进而从中找到问题,这个步骤所需的时间肯定是远大于初始添加索引所需的时间,并且可能会遗漏一部分的索引。
   当然索引也并不是越多越好,我曾经遇到过这样一个问题:某台MySQL服务器iostat显示磁盘使用率一直处于100%,经过分析后发现是由于开发人员添加了太多的索引,在删除一些不必要的索引之后,磁盘使用率马上下降为20%。可见索引的添加也是非常有技术含量的

4、理解索引的数据结构(储备知识)

1)机械磁盘一次IO的时间

机械磁盘一次io的时间 = 寻道时间 + 旋转延迟 + 传输时间

#寻道时间
道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下


#旋转延迟
旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;


#传输时间
传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计,所以访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms左右,这9ms对于人来说可能非常短,但对于计算机来可是非常长的一段时间,长到什么程度呢?
  一台500 -MIPS(Million Instructions Per Second)的机器每秒可以执行5亿条指令,因为指令依靠的是电的性质,换句话说执行一次IO的时间可以执行约450万条指令,数据库动辄十万百万乃至千万级数据,每次9毫秒的时间,显然是个灾难。
2)磁盘的预读
#考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一些优化:
当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO,这个理论对于索引的数据结构设计非常有帮助
3)索引原理(精髓提炼)
#索引的目的
   在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。相似的例子还有:查字典,查火车车次,飞机航班等


#索引的本质:
   通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据



#数据库索引:
    数据库索引也是一样的,但显然要复杂的多,因为不仅面临着等值查询,还有范围查询(><、between、in)、模糊查询(like)、并集查询(or)等等
    数据库应该选择怎么样的方式来应对所有的查询问题?
      字典的例子,能不能把数据分成段,然后分段查询呢?最简单的如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段......这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。但如果是1千万的记录呢,分成几段比较好?稍有算法基础的同学会想到搜索树,其平均复杂度是lgN,具有不错的查询性能。但这里我们忽略了一个关键的问题,复杂度模型是基于每次相同的操作成本来考虑的。而数据库实现比较复杂,一方面数据是保存在磁盘上的,另外一方面为了提高性能,每次又可以把部分数据读入内存来计算,因为我们知道访问磁盘的成本大概是访问内存的十万倍左右,所以简单的搜索树难以满足复杂的应用场景

二、索引分类

【索引结构图】

在这里插入图片描述

1、索引类型

#B+树索引:(等值查询与范围查询都快)
二叉树->平衡二叉树->B树->B+树
在B+树里面,非叶子节点不再存储数据,仅仅存在索引,而叶子这点存储具体的数据


#HASH索引:(等值查询快,范围查询慢)
将数据打散再去查询
MySQL并没有显式支持Hash索引,而是作为内部的一种优化。
具体在Innodb存储引擎里,会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,二级索引成为热数据,就为之建立hash索引
因此,在MySQL的Innodb里,对于热点的数据会自动生成Hash索引,这种hash索引,根据其使用的场景特点,也叫自适应Hash索引


#fulltext index(全文索引): (mysql5.6之前,只有myisam支持全文索引,到了mysql5.6,innodb开始支持全文索引)
通过关键字的匹配来进行查询,类似于like的模糊匹配
默认全文搜索不区分大小写


ps :like + %在文本比较少时是合适的,但是对于大量的文本数据检索会非常的慢
  全文索引在大量的数据面前能比like快得多,但是准确度很低
  百度在搜索文章的时候使用的就是全文索引

2、各种存储引擎(支持的索引类型)

在这里插入图片描述

#InnoDB存储引擎
  支持事务,支持行级别锁定,支持 B-tree(默认)、Full-text 等索引,不支持 Hash 索引;


#MyISAM存储引擎
  不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;


#Memory存储引擎
 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;

3、myisam与innodb对比(索引)

mysql默认的存储引擎是innodb,而innodb存储引擎的索引模型/结构是B+树
在这里插入图片描述

4、InnoDB的两类索引

【聚簇索引】

如果表设置了主键,则主键就是聚簇索引
如果表没有主键,则会默认第一个NOT NULL,且唯一(UNIQUE)的列作为聚簇索引
以上都没有,则会默认创建一个隐藏的row_id作为聚簇索引
在这里插入图片描述

InnoDB的聚簇索引的叶子节点存储的是行记录(其实是页结构,一个页包含多行数据),InnoDB必须要有至少一个聚簇索引,由此可见,使用聚簇索引查询会很快,因为可以直接定位到行记录
【非聚簇索引】

普通索引也叫二级索引,除聚簇索引外的索引,即非聚簇索引,InnoDB的普通索引叶子节点存储的是主键(聚簇索引)的值,而MyISAM的普通索引存储的是记录指针

在这里插入图片描述

三、索引的数据结构

innodb存储引擎默认的索引结构为B+树
而B+树是由二叉树、平衡二叉树、B树再到B+树一路演变过来的

【索引的创建】

#为某个字段创建索引,即以某个字段的值为基础构建索引结构,那么如何构建呢?(分为两大步骤)
  1、提取每行记录中该字段的值,以该值当作key,至于key对的value是什么?每种索引结构各不相同
  2、然后以key值为基础构建索引结构
【示列】
1)#为user表的id字段创建索引,会以每条记录的id字段值为基础生成索引结构
create index 索引名 on user(id);
#使用索引
select * from user where id = xxx;



2)#为user表的name字段创建索引,会以每条记录的name字段值为基础生成索引结构
create index 索引名 on user(id);
#使用索引
select * from user where name = xxx;

1、二叉查找树

【二叉查找树简述】

特点:任何节点的左子节点的键值都小于当前节点的键值与根节点,右子节点的键值都大于当前节点的键值与根节点

    二叉查找树 (Binary Search Tree)(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的 二叉树 :
 #特点: 
    若它的左子树不空,则左子树上所有结点的值均小于它的 根结点 的值; 
    若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树 。
    二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,
    例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作

user表,我们以id字段值为基础创建索引
在这里插入图片描述

1)二叉查找树的构建
1)#提取每一条记录的id值作为key值,value为本行完整记录
key    value
10     (10,zs)
7      (7,ls)
13     (13,ls)
5      (5,ls)
8      (8,ls)
12     (12,ls)
17     (17,ls)


2)#以key值的大小为基础构建二叉树,如上图
  二叉查找树的特点:
  就是任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值
  顶端的节点我们称为根节点,没有子节点的节点我们称之为叶节点
2 )二叉查找树的使用
#示列:
1#如果我们需要查找id=12的用户信息
select * from user where id=12;


2#利用我们创建的二叉查找树索引,查找流程如下:
   1、将根节点作为当前节点,把12与当前节点的键值10比较,12大于10,接下来我们把当前节点>的右
子节点作为当前节点。
   2、继续把12和当前节点的键值13比较,发现12小于13,把当前节点的左子节点作为当前节点。
   3、把12和当前节点的键值12对比,12等于12,满足条件,我们从当前节点中取出data,即id=1>2,name=xm


  ps : 利用二叉查找树我们只需要3次即可找到匹配的数据。如果在表中一条条的查找的话,我们需要6次才能找到,高效的提升了查询速度

2、平衡二叉树

特点:任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值

【平衡二叉树简述】
   平衡二叉树也叫自平衡二叉搜索树(Self-Balancing Binary Search Tree),所以其本质也是一颗二叉搜索树,不过为了限制左右子树的高度差,避免出现倾斜树等偏向于线性结构演化的情况,
   所以对二叉搜索树中每个节点的左右子树作了限制,左右子树的高度差称之为平衡因子,树中每个节点的平衡因子绝对值不大于 ,
   此时二叉搜索树称之为平衡二叉树
1)平衡二叉树的弊端
由上所示的二叉树,我们可以快速地找到数据,但是,但是,但是让我们看到二叉查找树的特点,所以,依据二叉查找树的特点,二叉树也可以由下这样构造的

在这里插入图片描述

这个时候可以看到我们的二叉查找树变成了一个链表。如果我们需要查找id=17的用户信息,我们需要查找7次,也就相当于全表扫描了。 导致这个现象的原因其实二叉查找树变得不平衡了,也就是高度太高了,从而导致查找效率的不稳定。 为了解决这个问题,我们需要保证二叉查找树一直保持平衡,就需要用到平衡二叉树了
   平衡二叉树又称AVL树,在满足二叉查找树特性的基础上,要求每个节点的左右子树的高度不能超过1
2)平衡二叉树和非平衡二叉树的对比

【非平衡二叉树转平衡二叉树】

在这里插入图片描述

由平衡二叉树的构造我们可以发现第一张图中的二叉树其实就是一棵平衡二叉树。
   平衡二叉树保证了树的构造是平衡的,当我们插入或删除数据导致不满足平衡二叉树不平衡时,平衡二叉树会进行调整树上的节点来保持平衡。
   平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快


ps :基于平衡二叉树构建索引的结构就可以了快速的查询数据呢?答案是否!
    对于海量数据文件,平衡二叉树还是不够快,不够高效的查询数据,由此可见,换可以进行更好的优化,如下所示

3、B 树

【B 树的概述】

B树是一种自平衡树数据结构,它维护有序数据并允许以对数时间进行搜索,顺序访问,插入和删除。B树是二叉搜索树的一般化,因为节点可以有两个以上的子节点。[1]与其他自平衡二进制搜索树不同,B树非常适合读取和写入相对较大的数据块(如光盘)的存储系统。它通常用于数据库和文件系统

B-树,即为B树,因为B树的原英文名称为B-tree
B-tree就是指的B树,目前理解B的意思为平衡
B树的出现是为了弥合不同的存储级别之间的访问速度上的巨大差异,实现高效的 I/O。
平衡二叉树的查找效率是非常高的,并可以通过降低树的深度来提高查找的效率。但是当数据量非常大,树的存储的元素数量是有限的,这样会导致二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下。另外数据量过大会导致内存空间不够容纳平衡二叉树所有结点的情况。B树是解决这个问题的很好的结构
1)B 树的使用

在这里插入图片描述

1》首先,因为内存的易失性。一般情况下,我们都会选择将user表中的数据和索引存储在磁盘这种外围设备中。但是和内存相比,从磁盘中读取数据的速度会慢上百倍千倍甚至万倍,所以,我们应当尽量减少从磁盘中读取数据的次数。


2》另外,从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读。 如果我们能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那我们查找数据的时间也会大幅度降低。


3》所以,如果我们单纯用平衡二叉树这种数据结构作为索引的数据结构,即每个磁盘块只放一个节点,每个节点中只存放一组键值对,此时如果数据量过大,二叉树的节点则会非常多,树的高度也随即变高,我们查找数据的也会进行很多次磁盘IO,查找数据的效率也会变得极低


4》综上所述,如果我们能够在平衡二叉的树的基础上,把更多的节点放入一个磁盘块中,那么平衡二叉树的弊端也就解决了,即构建一个单节点可以存储多个键值对的平衡树,这就是B树
2)B树的演变

B树(Balance Tree)即为平衡树的意思,下图即是一颗B树
【B树的结构】在这里插入图片描述

从上图可以看出,B树相对于平衡二叉树,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点,子节点的个数一般称为阶,上述图中的B树为3阶B树,高度也会很低。 基于这个特性,B树查找数据读取磁盘的次数将会很少,数据的查找效率也会比平衡二叉树高很多
    假如我们要查找id=28的用户信息,那么我们在上图B树中查找的流程如下:
    1、先找到根节点也就是页1,判断28在键值17和35之间,我们那么我们根据页1中的指针p2找到页3
    2、将28和页3中的键值相比较,28在26和30之间,我们根据页3中的指针p2找到页8。
    3、将28和页8中的键值相比较,发现有匹配的键值28,键值28对应的用户信息为(28,bv)


#注意:
  1、B树的构造是有一些规定的,但这不是本文的关注点,有兴趣的同学可以令行了解。

  2、B树也是平衡的,当增加或删除数据而导致B树不平衡时,也是需要进行节点调整的。
3)B 树的转变
  由上可知B树,B树是否就是索引的最终结构了呢?答案是no,B树只擅长做等值查询,而对于范围查询(范围查询的本质就是n次等值查询),或者说排序操作,B树也帮不了我们

#示列:
select * from user where id=3;   -- 擅长等值查询
select * from user where id>3;   -- 不擅长范围查询

ps :对于更快的查询,且支持多方位,多功能的查询的方式,对B树进行优化,由此演化出B+树,如下所示

4、B +树

【B+树的基本概述】
B+树是B树的一种扩展
在B+树里面,非叶子节点不再存储数据,仅仅存在索引,而叶子这点存储具体的数据,并且最底层的数据直接之间从做到右是按照从小到大的顺序分布,并且是一个双链表的结构。
也就是说的所有的关键码均出现在叶节点上,各层节点中的关键码均是下一层相应节点中的最大或者最小的关键码的复写

B+树的结构图:
在这里插入图片描述

1)B+树和B树的不同
1> B+树非叶子节点non-leaf node上是不存储数据的,仅存储键,而B树的非叶子节点中不仅存储键,也会存储数据。B+树之所以这么做的意义在于:树一个节点就是一个页,而数据库中页的大小是固定的,innodb存储引擎默认一页为16KB,所以在页大小固定的前提下,能往一个页中放入更多的节点,相应的树的阶数(节点的子节点树)就会更大,那么树的高度必然更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。


2> B+树的阶数是等于键的数量的,例如上图,我们的B+树中每个节点可以存储3个键,3层B+树存可以存储 3*3*3 =9个数据。所以如果我们的B+树一个节点可以存储1000个键值,那么3层B+树可以存储1000×1000×1000=10亿个数据。而一般根节点是常驻内存的,所以一般我们查找10亿数据,只需要2次磁盘IO,真是屌炸天的设计。


3> 因为B+树索引的所有数据均存储在叶子节点leaf node,而且数据是按照顺序排列的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B树因为数据分散在各个节点,要实现这一点是很不容易的。而且B+树中各个页之间也是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。其实上面的B树我们也可以对各个节点加上链表。其实这些不是它们之前的区别,是因为在mysql的innodb存储引擎中,索引就是这样存储的。也就是说上图中的B+树索引就是innodb中B+树索引真正的实现方式,准确的说应该是聚集索引(聚集索引和非聚集索引下面会讲到)


ps :通过上图可以看到,在innodb中,我们通过数据页之间通过双向链表连接以及叶子节点中数据之间通过单向链表连接的方式可以找到表中所有的数据
    #注意:MyISAM中的B+树索引实现与innodb中的略有不同。在MyISAM中,B+树索引的叶子节点并不存储数据,而是存储数据的文件地址

四、聚集索引与非聚集索引

MySQL中,B+树索引按照存储方式的不同分为聚集索引和非聚集索引,这里主要介绍innodb存储引擎中的聚集索引和非聚集索引,我们上面提到的索引其实是聚集索引的实现方式

1、聚集索引

聚集索引(又称聚簇索引、主键索引,一张表必须有且只有一个):

以innodb作为存储引擎的表,表中的数据都会有一个主键,即使你不创建主键,系统也会帮你创建一个隐式的主键,这是因为innodb是把数据存放在B+树中的,而B+树的键用的就是主键,在B+树的叶子节点中,存储了表中所有的数据

这种以主键作为B+树索引的键值而构建的B+树索引,我们称之为聚集索引

2、非聚集索引

非聚集索引(又称非聚簇索引、辅助索引,一张表可以创建多个辅助索引):

以主键以外的列值作为键值构建的B+树索引,我们称之为非聚集索引。非聚集索引与聚集索引的区别在于非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据我们还需要根据主键再去聚集索引中进
行查找,这个再根据聚集索引查找数据的过程,我们称为回表

3、查找数据(聚集索引)

B+树索引结构
在这里插入图片描述

#利用聚集索引(主键索引)进行查找范围数据(找出id>=18并且id<40的用户数据)

sql语句:  select * from user where id>=18 and id <40#(id为主键)

#查找步骤如下:
   1> 首先查找数据,一般根节点都是常驻内存的,也就是说页1已经在内存中了,此时不需要到磁盘中读取数据,直接从内存中读取即可。从内存中读取到页1,要查找这个id>=18 and id <40或者范围值,我们首先需要找到id=18的键值。从页1中我们可以找到键值18,此时我们需要根据指针p2,定位到页3

   2> 从第一页定位到第三页,从页3中查找数据,我们就需要拿着p2指针去磁盘中进行读取页3,从磁盘中读取页3后将页3放入内存中,然后进行查找,我们可以找到键值18,然后再拿到页3中的指针p1,定位到页8
  
   3> 同样的页8页不在内存中,我们需要再去磁盘中将页8读取到内存中。将页8读取到内存中后。因为页中的数据是链表进行连接的,而且键值是按照顺序存放的,此时可以根据二分查找法定位到键值18。此时因为已经到数据页了,此时我们已经找到一条满足条件的数据了,就是键值18对应的数据。因为是范围查找,而且此时所有的数据又都存在叶子节点,并且是有序排列的,那么我们就可以对页8中的键值依次进行遍历查找并匹配满足条件的数据。我们可以一直找到键值为22的数据,然后页8中就没有数据了,此时我们需要拿着页8中的p指针去读取页9中的数据。

   4> 因为页9不在内存中,就又会加载页9到内存中,并通过和页8中一样的方式进行数据的查找,直到将页12加载到内存中,发现41大于40,此时不满足条件。那么查找到此终止。最终我们找到满足条件的所有数据为:(18,kl),(19,kl),(22,hj),(24,io),(25,vg),(29,jk),(31,jk),(33,rt),(34,ty),(35,yu),(37,rt),(39,rt)。总共12条记录

利用聚集索引(主键索引)进行查找范围数据流程图
在这里插入图片描述

4、查找数据(非聚集索引)

B+树索引结构
在这里插入图片描述

提出示列:
在这里插入图片描述
对于非聚集索引,在叶子节点中,不再存储所有的数据了,存储的是键和主键
对于叶子节点中的x-y,比如10-23。左边的10表示的是索引的键值,右边的23表示的其对应的主键值
假设查找33的用户信息,sql语句:
select * from user where luckNum=33; (luckNum为主键)

#使用非聚集索引查找数据
    使用非聚集索(辅助索引或者二次索引)引查找数据,与聚集索引是一样的,主不过设置查找主键的不同,查询效率的快慢,如果查找的数据不存在辅助索引里(非聚集索引),就会重新会回到根节点进行重新查询(回表操作),非聚集索引与聚集索引相互对应,根据查找的数据内容有关系,非聚集索引(二次索引)查找的数据内容不够全面,而聚集索引,进行的查找的是全表数据
    如果使用select查询要是 * ,即所有字段值,包含字段对应的所有数据,使用辅助索引很难查到,准确类说是查不到,借助聚集索引,才能查询出来,在辅助索引中并不存,所以找到主键后我们需要再到聚集索引中查,找具体对应的数据信息

非聚集索引查找具体流程图:
在这里插入图片描述
MyISAM中:聚集索引和非聚集索引的叶子节点都会存储数据的文件地址

5、覆盖索引与回表操作

【覆盖索引】

覆盖索引:使用索引查找,命中了某棵索引树,然后在其叶子节点就找到了你想要的值,即不需要回表操作

注解覆盖索引:只需要在一棵索引树上就能获取SQL所需的所有列字段数据,无需回表,速度更快,效率更高

【覆盖索引的实现】
1#将被查询的字段,建立到联合索引里去。
select id,age from user where age = 10;

#注解  explain分析:
       因为age是普通索引,使用到了age索引,通过一次扫描B+树即可查询到相应的结果,这样就实现了覆盖索引

在这里插入图片描述

2)#select id,age,name from user where age = 10;
#注解  explain分析:
       age是普通索引,但name列不在索引树上,所以通过age索引在查询到id和age的值后,需要进行回表再查询name的值。此时的Extra列的NULL表示进行了回表查询

在这里插入图片描述

#为了实现索引覆盖,需要建组合索引idx_age_name(age,name)
drop index idx_age on user;
create index idx_age_name on user(`age`,`name`);

#注解  explain分析:
      此时字段age和name是组合索引idx_age_name,查询的字段id、age、name的值刚刚都在索引树上,只需扫描一次组合索引B+树即可,这就是实现了索引覆盖,此时的Extra字段为Using index表示使用了索引覆盖。
【简单示列】
#示列一:
1#使用辅助索引查找
create index xxx on user(name);    -- #设置主键为name


2)# 使用sql查询语句进行查找name字段名为hzl的数据
select name from user where name="hzl";    -- # 查找过程中,直接查找到指定name=hzl的数据,即为覆盖索引



#示列二:
#使用主键字段当作条件(如果id字段是主键,那么使用select * 也覆盖了索引)
select  * from user where id=3;    -- #直接直接使用id当查询条件,相当对于之上效率最高,建议设置id为主键
【回表操作】

回表操作:命中了辅助索引,然后要找的字段值不存在与辅助索引的叶子节点上,则需要根据拿到的主键值再去聚集索引(主键索引)中查询一遍,然后再聚集索引的叶子节点找到你想要的内容

注解回表操作:先通过普通索引的值定位聚簇索引值,再通过聚簇索引(主键索引)的值定位行记录数据,需要扫描两次索引B+树,它查找效率较扫一遍索引树更低

#回表操作的使用
create index xxx on user(name);   -- #设置索引为name字段


#使用查询索引进行回表操作
select name,age from user where name="hzl";   -- #查询索引name=hzl的数据,如果只查询name的字段包含hzl的数据,可不进行回表操作,但是要包含的数据不在索引范围,则需要重新进行查询,即回表操作
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值