MySQL索引3——Explain关键字和索引优化(SQL提示、索引失效、索引使用规则)

news2024/9/25 17:18:17

目录

Explain关键字 索引性能分析

Id ——select的查询序列号

Select_type——select查询的类型

Table——表名称

Type——select的连接类型

Possible_key ——显示可能应用在这张表的索引

Key——实际用到的索引

Key_len——实际索引使用到的字节数

Ref    ——索引命中的列或常量

Rows——预计select语句要检查的行数

Filtered——返回结果的行数占读取行数的百分比

Extra——显示额外的信息

索引的优化

SQL提示

最左前缀法则

索引失效情况

索引的设计原则


Explain关键字 索引性能分析

Explain可以应用于SELECT、DELETE、INSERT、REPLACE、UPDATE语句

通过Explain关键字可以看到SELECT语句的执行计划,即可以查看到MySQL如何处理SELECT语句,通过Explain显示的结果来决定如何优化

具体的作用有

  1. 查看表的读取顺序
  2. 查看此语句可以使用哪些索引
  3. 此语句实际使用了哪些索引
  4. 查看此语句查询了多少行数据

explain语法

在任意的SELECT语句之前加上关键字 Explain或者Desc

EXPLAIN SELECT * FROM 表名;

使用Explain后返回的结果

查询结果的各个字段

Id ——select的查询序列号

表示查询中SQL执行的顺序;id相同时的执行顺序为从上到下;id不同时值越大越先执行

对于单表查询,查询一次一般会产生一个id的一行信息

explain select * from user;

对于多表查,查询一次一般会产生相同id的多行信息

 explain select * from career,user where career.id = user.career_id;

对于子查询,查询一次一般会产生不同id的多行信息

explain select * from user where user.career_id = (select id from career where id=1);

Select_type——select查询的类型

常见的取值有

SIMPLE:简单的select查询类型;查询语句中不包含子查询或UNION

PRIMARY:当查询中包含子查询或UNION时,即外层的查询为此查询类型

SUBQUERY:在SELECT或WHERE中包含了子查询时会被标记为此查询类型

DERIVED:在FROM列表中包含的子查询被标记为此查询类型(MySQL会将此子查询的查询结果作为临时表—派生表)

explain

select * from

 (select origo,count(*) as number from staff1 group by origo) as emp    

 where emp.number > 2; #根据居住地分组,并查询居住地人数大于2的(派生表的别名为emp)

UNION:在UNION中的第二个和随后的SELECT语句被标记为UNION(如果UNION被FROM子句中的子查询包含,则它的第一个SELECT会被标记为DERIVED)

explain

select origo,count(*) as number  from staff2 group by origo

union

select origo,count(*) as number  from staff1 group by origo;

explain

select origo,count(*) as number  from staff2 group by origo

union

select * from (select origo,count(*) as number from staff1 group by origo) as emp  where emp.number > 2;

 UNION RESULT:表示对应UNION的结果(UNION和UNRESULT一般会成对出现)

Table——表名称

显示这一行的数据是关于哪张表的,显示结果可能为表的名称、<derivedX>、<unionX1,X1>等

<derivedX>

当from子句中有子查询时,table列为<derivedX>的格式(x为id值),对应子查询返回的临时表(派生表)

<unionX1,X1>

当存在union时,union result的table列为<unionX1,X1>的格式;X1和X2表示参与union的表的id序号

Type——select的连接类型

select的连接类型是查看索引执行情况的一个重要指标,就是MySQL如何查找数据表中的记录

连接类型的性能由好到差为NULL、system、const、eq_ref、ref、fulltext、ref_or_null、index_merge、unique_subquery、index_subquery、range、index、all

重点关注的是:NULL、system、const、eq_ref、ref、range、index、all

在优化时尽量优化为性能好的(当查询时不查询任何表时才会出现NULL)

主键或唯一索引查询会出现const,使用非唯一性索引查询时会出现ref

一般我们最好保证查询时type达到range、ref级别

All和Index都是读全表,只是Index读的是索引树,All读的是数据表

不同连接类型代表的含义(通过Staff1表来模拟现象)

Fulltext:       当查询使用到全文索引时的连接类型

Ref_or_null: 类似于ref,也是非唯一性索引扫描;不过MySQL还会扫描哪些行包含了NULL

Index_merge: 表示使用了索引合并优化(即一个中使用到了多个索引)

Unique_subquery:类似于eq_ref,唯一性索引扫描;但是使用了IN查询,并且子查询查询字段为主键或唯一索引

Index_subquery:  类似于unique_subquery;不过子查询查询字段为非唯一索引

Null:   查询时不查询任何表(MySQL在优化阶段会分析查询语句,以此来判断是否需要访问表)或者在查询的值在此字段找不到,并且此字段建立了唯一索引

explain select min(id) from staff1; #查看主键的最小id

System:表只有一行记录;是Cost的特殊情况,平时不会出现可忽略

Const: 表示通过索引一次就找到了要查询的记录(一般存在于单表查询时,主键或唯一索引作为查询条件)

explain select * from staff1 where number=2021004;

 Eq_ref: 唯一性索引扫描;对于每个索引键,表中只有一条记录与之匹配;(一般存在于多表查询时,使用主键或唯一索引扫描作为查询条件)

explain select s1.*,a1.* from staff1 s1, account a1 where s1.id = a1.id;

 Ref:      非唯一性索引扫描;返回匹配某个单独值的所有行,可能会找到多个符合条件的行,属于查找和扫描的混合体(用于常规索引、联合索引情况)

explain select * from staff1 where origo='重庆';

Range:范围查询;当给一个字段添加索引之后,使用范围作为此字段的条件进行数据查询时的连接类型(般就是在where语句中出现了between、<、>、in等的查询)

explain select * from staff1 where number>2021001;

Index:index类型值遍历索引树(通过遍历索引树来查找数据,需要查找的字段都已经建立了索引-主键索引、唯一索引、常规索引等)

explain select id,number from staff1;

ALL:将遍历全表已找到匹配的行,没有使用索引

Possible_key ——显示可能应用在这张表的索引

该值为一个或多个

此字段显示的索引不一定会被查询使用到,可能会出现索引失效的问题

当Select语句发现可以使用多个索引的时候,可以通过SQL提示来建议Mysql语句使用指定的索引,可以避免SQL使用了性能比较低的索引(例如如果同时存在唯一索引和常规索引,可以建立SQL使用唯一索引)

Key——实际用到的索引

如果没有使用索引,则为NULL

哪些情况会导致有可用索引但是实际上没有使用到索引呢?

1、对于联合索引来说,没有遵守最左前缀法则

2、范围查询时使用到>或<,会导致范围查询右侧的列索引失效

3、在Where之后的索引列上进行运算操作(包含函数、比较运算符、谓词等)

4、字符串类型字段的值使用时,如果不加引号,存在隐式类型转换,索引将失效

5、当对头部进行模糊匹配时,索引会失效(即Like(%字符)或者Like(_字符))

6、用or分隔开的条件,如果or前条件中的列有索引,而后面的列中没有索引,那么or前面的索引不会被用到

7、数据分布影响;如果MySQL评估使用索引查询比全表查询更慢,则不使用索引,使用全表查询

如何规避索引失效呢?————具体在索引的优化介绍

1、联合索引遵守最左前缀法则,在创建联合索引时尽量将使用频率高的字段放在最左端

2、在范围查询时尽量使用过>=或者<=来规避范围查询

3、尽量不对索引列进行运算操作

4、在使用属于字符串类型的字段时,需要对其值加上引号

5、尽量使用尾部模糊匹配来代替头部模糊匹配;当对尾部进行模糊匹配时,则索引不会失效(即Like(字符%)或者Like(字符_))

6、只有当or前后都是用到索引时,索引才会失效

Key_len——实际索引使用到的字节数

表明了在索引中使用的字节数,通过此值可以大致估算出使用了索引中的哪些列

Key_len的计算规则

当字段允许为Null时,比不允许为Null大1个字节

不同的数据类型,占用的字节数时不同的,详情可以参考以下官方文档(介绍的是不允许为空的情况)

MySQL :: MySQL 8.0 Reference Manual :: 11.7 Data Type Storage Requirements

对于字符串数据类型来说,其占用的字节数还跟使用的字符编码有关

GBK               2字节

UTF8             3字节

ISO8859-1     1字节

GB2312         2字节

UTF-16          2字节

Ref    ——索引命中的列或常量

表进行数据查找时使用字段、常量、函数的结果等

常量:           const

空:              NULL

字段:           数据库名.表名.字段名

函数的结果:func(如果要想查看是哪个函数,可以在Explain语句后跟上SHOW WARNING语句)

explain select origo from staff1 where origo='重庆';

explain select * from staff1 where id in (select id from staff1 where id > 2);

Rows——预计select语句要检查的行数

mysql估计要读取并检查的行数;并不是结果的行数

在innoDB引擎中的表中,是一个估计值,不是很准确

Filtered——返回结果的行数占读取行数的百分比

该值越大越好

Extra——显示额外的信息

通过此字段显示的额外信息,也可以进行查询的优化(不同MySQL版本显示的内容可能会有些许差别)

Using Index:查找使用了索引,并且返回所需要的数据在该索引列中就可以找到(无需回表查询)

Using Where:先读取整行数据,再按照Where条件进行查询(符合就留下,不符合则丢弃)

Using Join Buffer:表示查询使用了连接缓冲(多用于多表连接查询)

Using Index Condition         查找使用了索引,但是需要回表查询数据—此种情况一般需要优化(可以使其满足覆盖索引条件来避免回表查询)

Using Temporary:查找使用了临时表(多见于group by语句)--此种情况一般需要优化(优先通过建立索引解决)

Using Filesort:表示对查询的结果进行全表扫描然后进行排序(多见于order by语句)--此种情况一般需要优化(优先通过建立索引解决)


索引的优化

通过以下方式,避免索引失效,并且可以手动选择索引进行索引查询;使得索引的到最大利用

SQL提示

是优化数据库的一个重要手段,就是在SQL语句中加入一些人为的提示来达到优化操作的目的

SQL提示的字段

USE INDEX            建议数据库使用哪个索引(当一列属于多个索引类型式,建议此列使用哪种类型的索引,MySQL可能不会采用此建议)

IGNORE INEDX     告诉数据库不要用哪个索引      

FORCR INDEX       告诉数据库必须使用哪个索引

SQL提示的格式

SELECT 字段列表 FROM 表名 USE INDEX (索引名称) WHERE 判断条件; 

情景模拟

针对上述表,我们为origo、age创建了联合索引,现在我们再针对origo创建一个常规索引

 explain select origo from staff1 where origo='重庆' and age > 18; #此时我们查询此语句走的是联合索引  我们可以通过语句修改使其走单列索引

explain select origo from staff1 use index (as_origo) where origo='重庆' and age > 18;

最左前缀法则

主要针对联合索引,如果索引为联合索引,则要遵守最左前缀法则

最左前缀法则的要求

在使用联合索引进行查询时,查询从联合索引的最左列开始,并且不跳过索引中的列,可以跳过最右边的一列或多列;

在查询时,如果中途跳过了联合索引中的某一列,索引部分失效(此列之后的列索引失效),即无法进行索引查询,只可以进行全文查询

在查询时,如果最左边的列不存在,则不走索引,走全文扫描(即进行联合查询时必须包含最左列)  在查询时不用关心顺序,只要存在就可以了

create index as_origo on staff1(origo,age,name); #创建时由左到右创建,左边一般为查询频率高的

explain select * from staff1 where origo='重庆';

explain select * from staff1 where origo='重庆' and age = 22 ;    #查询时,也是从左到右查询;此时使用了索引

explain select * from staff1 where origo='重庆' and name='老六';   #此时origo使用了索引,name没有使用索引(通过key_len使用索引的字节数判断)

explain select * from staff1 where age = 22 ;   #此时没有使用索引(没有包含origo字段)

索引失效情况

范围查询

在联合索引中,出现范围查询(>或<)时,范围查询右侧的列索引失效

尽量使用过>=或者<=来规避范围查询

运算操作

在索引列上进行运算操作时,索引列将失效;运算包括使用函数、比较运算符、谓词等

字符串数据类型

字符串类型字段使用时,如果不对其值加引号,则存在隐式类型转换,索引将失效

Like字段模糊查询

当对尾部进行模糊匹配时,则索引不会失效(即Like(字符%)或者Like(字符_))

当对头部进行模糊匹配时,索引会失效(即Like(%字符)或者Like(_字符))

or连接条件

用or分隔开的条件,如果or前/后的条件中的列有索引,而后/前面的列中没有索引,那么or前/后面的索引不会被用到;

只有当or前后都是用到索引时,索引才会失效

数据分布影响

如果MySQL评估使用索引查询比全表查询更慢,则不使用索引,使用全表查询(一般用于大小判断的时候会出现)

由于B+树是顺序链表,当第一个叶子就符合或者前几个叶子就符合时,后面的叶子就必然也符合;此时MySql就判断使用全表查询更快,就会不适用索引,使用全表查询了

即:当要查询的结果占全表很大的比例时,可能就进行全表查询了

索引的设计原则

  1. 针对数据量较大(100多万数据及以上)、且查询比较频繁的表建立索引(很少查询,没有必要建立索引
  2. 针对于常作为查询条件(Where)、排序(Order By)、分组(Group By)操作的字段建立索引
  3. 尽量区分度高的列作为索引,尽量建立唯一索引;区分度越高,使用索引的效率越高
  4. 如果是字符串类型的字段,字段的长度较长,可以针对字段的特点,建立前缀索引
  5. 尽量使用联合索引,减少单列索引;查询时联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率
  6. 控制索引的数量,索引越多,维护索引结构的代价也就越大,会影响增删改的效率
  7. 如果索引列不能存储Null,就在创建表时使用NOT NULL约束此字段;当MySQL优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询

总结

1、查询效率不高,首先使用explain分析:

如果发现没有索引,可以创建索引

如果发现是单列索引,要注意是否存在索引失效

如果发现是联合索引,要注意是否遵守最左匹配原则

2、尽可能地使得查询语句扫描更少地行数、表、列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/838749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安捷伦54642D混合信号示波器

安捷伦54642D混合信号示波器 附加功能: 带宽:500兆赫&#xff08;131---4587---6435&#xff09; 通道:2个模拟和16个数字 采样速率:2Gs/s 记录长度:8分钟 获得专利的高清显示系统 灵活触发&#xff0c;包括CAN、I2C、LIN、SPI和USB 接口总线上的深层存储器传输 强大、灵活的触…

嵌入式笔试面试刷题(day5 IIC详解)

文章目录 前言一、IIC需要几根线分别是什么线二、IIC优势三、IIC可以挂载多少个从设备&#xff0c;主设备1.从设备数量2.主设备数量 四、IIC是全双工还是半双工五、SDA和SCL为什么配置为上拉开漏输出模式1.为什么要配置为开漏输出不能是推挽输出a.实现线与功能b.保护设备不会被…

XXL-JOB执行器集群及分片功能

系统架构图 XXL-JOB职责划分 准备工作 1.下载代码 https://gitee.com/xuxueli0323/xxl-job/tree/2.3.0/ 2.将xxl-job sql执行 3.修改xxl-job-admin数据库链接及账号密码 4.创建日志目录修改日志文件指定输出目录 5.启动项目后访问xxl-job-admin http://localhost:8080/xxl-…

GD32F103*固件库移植μCOS-Ⅲ详细教程与解析(最终版本已上传,可下载)

GD32F103*固件库移植μCOS-Ⅲ详细教程与解析&#xff08;最终版本已上传&#xff0c;可下载&#xff09; GD32F103*移植μCOS-Ⅲ详细教程与解析&#xff0c;欢迎指正 文章目录 GD32F103*固件库移植μCOS-Ⅲ详细教程与解析&#xff08;最终版本已上传&#xff0c;可下载&#x…

GitHub上删除项目后,IDEA分享项目到GitHub提示Remote is already on GitHub

文章目录 一、错误信息二、解决方法1.删除GitHub上的项目2.找到项目里的.git隐藏文件3.找到config文件4.打开config文件&#xff0c;删除[remote "git-test"]及下面两行内容5.继续使用IDEA分享项目到GitHub即可 一、错误信息 二、解决方法 1.删除GitHub上的项目 2.…

亿邦智库天猫:2023年中国家电产业带白皮书(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 中国家电产业市场始于上个世纪80年代&#xff0c;经过近四十年的发展&#xff0c;中国家电产业经历了以产能为主导的“供给驱动〞 阶段、线下网点为主导的“溪道驱动”阶段&#xff0c;现已全面进入以…

Windows批处理基础

一、【echo】显示文本内容 echo | Microsoft Learnhttps://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/echo 显示消息或者打开或关闭命令回显功能。 如果不结合任何参数使用&#xff0c;echo 会显示当前回显设置。 1.1、echo显示文本常用命…

【GEMM预备工作】行主序和列主序矩阵的内存中的连续性,解决理解问题

在内存存储中&#xff0c;默认矩阵是按照行优先储存的&#xff0c;即矩阵的每一列在内存中是连续的。行优先矩阵储存中行数据是不连续的。 而对于列主序的矩阵&#xff0c;是按照列优先储存的&#xff0c;即矩阵的每一行在内存中是连续的。列优先矩阵储存中列数据是不连续的&am…

过滤器的使用和编码过滤器案例

过滤器的使用和编码过滤器案例 案例&#xff1a;设置UTF-8编码

Python - 【socket】 服务端Server异常重启处理简单示例Demo(二)

一. 前言 当socket服务端通信出现异常时&#xff0c;我们需要做重启程序&#xff0c;可根据具体场景做出选择 二. 示例代码 1. 重启服务 import socket import time import sys import tracebackHOST 127.0.0.1 # 服务器IP地址 PORT 8080 # 服务器端口号 BACKLOG 5 #…

七步成诗问题处理法

七步成诗问题处理法 来自麦肯锡咨询公司的经典工具&#xff0c;是各类问题处理的一种方法和逻辑&#xff0c;广泛应用于现代企业管理中&#xff0c;也适用于个人的问题处理。 模型介绍 职场中最重要的能力之一&#xff0c;一定是解决问题的能力。善于解决问题&#xff0c;通常…

台灯应该买什么样的才能护眼?教大家如何挑选护眼灯

家里顶灯太暗了且高度太高&#xff0c;还是原始的LED灯&#xff0c;晚上用着眼睛都有点难受&#xff0c;还好遇到了儿童护眼灯。下面小编为大家介绍下儿童护眼灯哪个牌子好&#xff1f;什么护眼台灯比较专业 护眼台灯怎么样选择 1、照度级别 台灯照度级别分为 A 级和 AA 级。…

Centos虚拟机忘记密码-修改密码

1.重启系统 2.在这个选择界面&#xff0c;按e建 3.找到如下位置&#xff0c;插入init/bin/sh 4.填写完成后按Ctrlx引导启动 5.输入mount -o remount, rw / (注意空格) 6.重置密码 出现以下为重置成功 7.执行touch /.autorelabel 8.退出exec /sbin/init 9.输入你的新密…

多态的使用

1、认识多态 面向对象三大特征&#xff1a;封装、继承、多态 什么是多态&#xff1f; 同类型的对象&#xff0c;表现出不同的形态。&#xff08;对象的多种形态。&#xff09; 多态的表现形式&#xff1f; 父类类型 对象名称 子类对象&#xff1…

SpringBoot项目-个人博客系统的实现

1.博客系统简要分析 一共有6个网页&#xff0c;分别是博客列表页面&#xff0c;博客详情页面&#xff0c;发布博客页面&#xff0c;博客登陆页面&#xff0c;博客更新页面&#xff0c;修改个人信息页面&#xff08;暂未实现&#xff09;&#xff0c;我们要实现的功能有&#xf…

什么是 MySQL 的“回表”?怎么减少回表的次数?

什么是 MySQL 的“回表”&#xff1f;怎么减少回表的次数&#xff1f; 索引结构 要搞明白这个问题&#xff0c;需要大家首先明白 MySQL 中索引存储的数据结构。这个其实很多小伙伴可能也都听说过&#xff0c;BTree 嘛&#xff01; BTree 是什么&#xff1f;那你得先明白什么…

使用Python将图像转换为PDF:一次性解决您的批量转换需求

导语&#xff1a; 在数字化时代&#xff0c;我们经常需要处理大量的图像文件。将这些图像转换为PDF格式可以方便地存档、分享和打印。本文将介绍如何使用Python编程语言将图像批量转换为PDF&#xff0c;并提供了一个简单易用的图形界面来跟踪转换进度。 准备工作 在开始之前…

AI编程工具Copilot与Codeium的实测对比

csdn原创谢绝转载 简介 现在没有AI编程工具&#xff0c;效率会打一个折扣&#xff0c;如果还没有&#xff0c;赶紧装起来&#xff0e; GitHub Copilot是OpenAi与github等共同开发的的AI辅助编程工具&#xff0c;基于ChatGPT驱动&#xff0c;功能强大&#xff0c;这个没人怀疑…

Linux进程(二)

文章目录 进程&#xff08;二&#xff09;Linux的进程状态R &#xff08;running&#xff09;运行态S &#xff08;sleeping&#xff09;阻塞状态D &#xff08;disk sleep&#xff09;深度睡眠T&#xff08;stopped&#xff09;状态X&#xff08;dead&#xff09;状态Z&#x…

2024年浙师大MBA项目招生信息全面了解

2024年全国管理类硕士联考备考已经到了最火热的阶段&#xff0c;不少考生开始持续将注意力集中在备考的规划中&#xff01;杭州达立易考教育整合浙江省内的MBA项目信息&#xff0c;为大家详细梳理了相关报考参考内容&#xff0c;方便大家更好完成择校以及针对性的备考工作。本期…