MySQL索引3——Explain关键字和索引使用规则(SQL提示、索引失效、最左前缀法则)

目录

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:通过表的索引或者全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序(多见于order by语句)----此种情况一般需要优化(优先通过建立索引解决)

一般需要将Using Filesort、Using Temporary、Using Index Condition 等优化为Using Index


索引的使用规则

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

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、尽可能地使得查询语句扫描更少地行数、表、列

3、如果对字符串创建了索引,尽可能减少字符串的长度(即为较短的字符串建立前缀索引)

4、尽量使得索引查询满足覆盖索引,避免回表查询

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习深度学习——注意力提示、注意力池化(核回归)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——常见循环神经网络结构&#xff08;RNN、LSTM、GRU&#xff09; &#x1f4da;订阅专栏&#xff1a;机器…

SqlServer基础之(触发器)

概念&#xff1a; 触发器&#xff08;trigger&#xff09;是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法&#xff0c;它是与表事件相关的特殊的存储过程&#xff0c;它的执行不是由程序调用&#xff0c;也不是手工启动&#xff0c;而是由事件来触发&#x…

JVM G1垃圾回收机制介绍

G1(Garbage First)收集器 (标记-整理算法)&#xff1a; Java堆并行收集器&#xff0c;G1收集器是JDK1.7提供的一个新收集器&#xff0c;G1收集器基于“标记-整理”算法实现&#xff0c;也就是说不会产生内存碎片。此外&#xff0c;G1收集器不同于之前的收集器的一个重要特点是&…

钓鱼攻击:相似域名识别及如何有效预防攻击

网络犯罪分子很乐意劫持目标公司或其供应商或业务合作伙伴的官方域名&#xff0c;但在攻击的早期阶段&#xff0c;他们通常没有这种选择。相反&#xff0c;在有针对性的攻击之前&#xff0c;他们会注册一个与受害组织的域名相似的域名 - 他们希望您不会发现其中的差异。此类技术…

SpringBoot 的自动装配特性

1. Spring Boot 的自动装配特性 Spring Boot 的自动装配&#xff08;Auto-Configuration&#xff09;是一种特性&#xff0c;它允许您在应用程序中使用默认配置来自动配置 Spring Framework 的各种功能和组件&#xff0c;从而减少了繁琐的配置工作。通过自动装配&#xff0c;您…

TepeScript 问题记录

问题 对object的所有属性赋值或清空&#xff0c;提示类型错误不能赋值 type VoiceParams {_id?: string | undefined;name: string;sex: string;vc_id: string;model_url: string;preview_url: string;isPrivate: boolean;visible: boolean; }const formData reactive<V…

【Minecraft】Fabric Mod开发完整流程2 - 创造模式物品栏与第一个方块

创造模式物品栏 添加到当前已有物品栏 再添加自定义的创造模式物品栏之前&#xff0c;请确保你的确有这个需求&#xff01;否则建议直接添加到当前已有的物品栏内部 创建新文件&#xff1a;com/example/item/ModItemGroup.java package com.example.item;import net.fabricmc.…

出于网络安全考虑,印度启用本土操作系统”玛雅“取代Windows

据《印度教徒报》报道&#xff0c;印度将放弃微软系统&#xff0c;选择新的操作系统和端点检测与保护系统。 备受期待的 "玛雅操作系统 "将很快用于印度国防部的数字领域&#xff0c;而新的端点检测和保护系统 "Chakravyuh "也将一起面世。 不过&#xf…

2024考研408-计算机网络 第五章-传输层学习笔记

文章目录 前言一、传输层提供的服务1.1、传输层的功能1.2、传输层的两个协议&#xff08;TCP、UDP&#xff09;1.3、传输层的寻址与端口&#xff08;常见端口介绍&#xff09; 二、UDP协议2.1、认识UDP功能和特点2.2、UDP首部格式2.3、UDP伪首部字段分析2.4、伪首部校验UDP用户…

【24择校指南】南京大学计算机考研考情分析

南京大学(A) 考研难度&#xff08;☆☆☆☆☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分数人数统计&#xff09;、院校概况、23初试科目、23复试详情、参考书目、各科目考情分析、各专业考情分析。 正文2178字&#xff0c;预计阅读&#xff1a;6分…

网络原理(JavaEE初阶系列11)

目录 前言&#xff1a; 1.网络原理的理解 2.应用层 2.1自定义协议的约定 2.1.1确定要传输的信息 2.1.2确定数据的格式 3.传输层 3.1UDP 3.1.1UDP报文格式 3.2TCP 3.2.1确认应答 3.2.2超时重传 3.2.3连接管理 3.2.3.1三次握手 3.2.3.2四次挥手 3.2.4滑动窗口 3.…

【JavaEE】Spring Boot - 配置文件

【JavaEE】Spring Boot 开发要点总结&#xff08;2&#xff09; 文章目录 【JavaEE】Spring Boot 开发要点总结&#xff08;2&#xff09;1. 配置文件的两种格式2. .properties 文件2.1 基本语法2.2 注释2.3 配置项2.4 主动读取配置文件的键值2.5 数据库的连接时的需要的信息配…

ChatGPT访问流量下降的原因分析

​自从OpenAI的ChatGPT于11月问世以来&#xff0c;这款聪明的人工智能聊天机器人就席卷了全世界&#xff0c;人们在试用该工具的同时也好奇该技术到底将如何改变我们的工作和生活。 但近期Similarweb表示&#xff0c;自去ChatGPT上线以来&#xff0c;该网站的访问量首次出现下…

面试热题(路径总和II)

给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 在这里给大家提供两种方法进行思考&#xff0c;第一种方法是递归&#xff0c;第二种方式使用回溯的方式进行爆…

Linux文件属性与权限管理(可读、可写、可执行)

Linux把所有文件和设备都当作文件来管理&#xff0c;这些文件都在根目录下&#xff0c;同时Linux中的文件名区分大小写。 一、文件属性 使用ls -l命令查看文件详情&#xff1a; 1、每行代表一个文件&#xff0c;每行的第一个字符代表文件类型&#xff0c;linux文件类型包括&am…

Javascript 正则

基本语法 定义 JavaScript种正则表达式有两种定义方式 构造函数 var regnew RegExp(<%[^%>]%>,g);字面量 var reg/<%[^%>]%>/g;g&#xff1a; global&#xff0c;全文搜索&#xff0c;默认搜索到第一个结果接停止i&#xff1a;ingore case&#xff0c;忽略…

小程序如何设置电子票

电子票是一种方便快捷的票务管理方式&#xff0c;可以帮助商家实现电子化的票务管理&#xff0c;提升用户体验。下面介绍&#xff1a;如何在小程序内&#xff0c;设置电子票以及用电子票购买商品。 1. 设置电子票套餐。可以新建一个商品&#xff0c;商品标题写&#xff1a;XX电…

UDP通信实验、广播与组播、本地套接字

文章目录 流程函数应用广播应用 组播&#xff08;多播&#xff09;本地套接字应用 流程 函数 返回值&#xff1a; 成功&#xff0c;返回成功发送的数据长度 失败&#xff0c;-1 返回值&#xff1a; 成功&#xff0c;返回成功接收数据长度 失败&#xff0c;-1 应用 广播 应用 …

android APP内存优化

Android为每个应用分配多少内存 Android出厂后&#xff0c;java虚拟机对单个应用的最大内存分配就确定下来了&#xff0c;超出这个值就会OOM。这个属性值是定义在/system/build.prop文件中. 例如&#xff0c;如下参数 dalvik.vm.heapstartsize8m #起始分配内存 dalvik.vm.…

搭建servlet服务

目录 servlet的生命周期 配置tomcat环境 创建web后端项目 配置web.xml http请求 get和post 其他请求 http响应 Servlet是Server Applet的简称&#xff0c;意思为用Java编写的服务器端的程序&#xff0c;它运行在web服务器中&#xff0c;web服务器负责Servlet和客户的通…