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、尽量使得索引查询满足覆盖索引,避免回表查询

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vs导出和导入动态库和静态库

1. 动态库和导出和导入 1.1 动态库的导出 1. 创建新项目 新建新项目&#xff0c;选择动态链接库&#xff08;DLL&#xff09;。 填写项目名称&#xff0c;并选择项目保存的路径&#xff0c;然后点击创建。 创建完成后&#xff0c;会自动生成如下所示文件&#xff0c;可以根据…

PostgreSQL-数据库命令

PostgreSQL-数据库命令 介绍 一个数据库是一个或多个模式的集合&#xff0c;而模式包含表、函数等。因此&#xff0c;完整的逻辑组织结构层次是服务器实例&#xff08;PostgreSQL Server&#xff09;、数据库&#xff08;Database&#xff09;、模式&#xff08;Schema&#…

jmeter 5.1彻底解决中文上传乱码

1.修改源码,然后重新打jar包,就是所有上传文件名重新获取文件名 参考链接:多种Jmeter中文乱码问题处理方法 - 51Testing软件测试网 2.修改Advanced,必须选java

API接口统一管理

API接口统一管理 在开发项目的时候,接口可能很多需要统一管理。在src目录下去创建api文件夹去统一管理项目的接口&#xff1b;这样便于后期维护和团队开发。 axios二次封装 对于axios不熟悉的话&#xff0c;建议先学习这篇文章:Axios的基本使用 在开发项目的时候避免不了与后…

App Cleaner Uninstaller for Mac 苹果电脑软件卸载工具

App Cleaner & Uninstaller 是一款非常有用的 Mac 应用程序清理和卸载工具。它可以彻底地清理系统中的应用程序、扩展和残留文件&#xff0c;以释放磁盘空间并优化系统性能。 此外&#xff0c;它还提供了磁盘空间监控和智能清理建议等功能&#xff0c;使用户可以轻松地管理…

STM32基础入门学习笔记:面包板 配件包扩展模块与编程

文章目录&#xff1a; 一&#xff1a;阵列键盘 1.阵列键盘测试程序 KEYPAD4x4.h KEYPAD4x4.c main.c 2.键盘中断测试程序 NVIC.h NVIC.c main.c 二&#xff1a;舵机控制 1.延时函数驱动舵机程序 SG90.h SG90.c main.c 2.PWM(脉冲宽度调制 脉宽调制/占空比)驱动…

Leetcode周赛 | 2023-8-6

2023-8-6 题1体会我的代码 题2我的超时代码题目体会我的代码 题3体会我的代码 题1 体会 这道题完全就是唬人&#xff0c;只要想明白了&#xff0c;只要有两个连续的数的和&#xff0c;大于target&#xff0c;那么一定可以&#xff0c;两边一次切一个就好了。 我的代码 题2 我…

应急响应-勒索病毒的处理思路

0x00 关于勒索病毒的描述 勒索病毒入侵方式&#xff1a;服务弱口令&#xff0c;未授权&#xff0c;邮件钓鱼&#xff0c;程序木马植入&#xff0c;系统漏洞等 勒索病毒的危害&#xff1a;主机文件被加密&#xff0c;且几乎难以解密&#xff0c;对主机上的文件信息以及重要资产…

NAT协议(网络地址转换协议)详解

NAT协议&#xff08;网络地址转换协议&#xff09;详解 为什么需要NATNAT的实现方式静态NAT动态NATNAPT NAT技术的优缺点优点缺点 NAT协议是将IP数据报头中的IP地址转换为另外一个IP地址的过程&#xff0c;主要用于实现私有网络访问公有网络的功能。这种通过使用少量的IP地址代…

【源码分析】Nacos自动注册源码分析

文章目录 服务注册&#xff08;AP协议&#xff09;服务发现&#xff08;CP协议&#xff09;Nacos是如何整合到SpringCloudAlibaba的&#xff1f; 服务注册&#xff08;AP协议&#xff09; Nacos提供了NamingService的registerInstance方法来提供服务注册的功能。 因此只要我们…

vue v-slot指令

目录 定义语法使用场景场景一场景二场景三tips只有一个默认插槽时 定义 在Vue中&#xff0c; v-slot 指令用于定义插槽的模板内容。它用于在父组件中传递内容到子组件中的插槽。 v-slot 指令可以用于 标签或组件标签上&#xff0c;以便在子组件中使用插槽。 语法 使用 v-slo…

16-1_Qt 5.9 C++开发指南_多语言界面

文章目录 1. 多语言界面设计概述2. tr()函数的使用3. 生成语言翻译文件4. 使用Qt Linguist 翻译 ts 文件5. 调用翻译文件改变界面语言5.1 生成qm文件5.2 项目启动时设置界面语言5.3 动态切换语言 1. 多语言界面设计概述 有些软件需要开发多语言界面版本&#xff0c;如中文版和…

自动化测试框架?数据驱动vs关键字驱动,该怎么做?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 对于自动化测试框…

BI报表工具有哪些作用?奥威BI全面剖析数据

BI报表工具有哪些作用&#xff1f;主要的作用是通过整合多业务来源数据&#xff0c;全面分析挖掘数据&#xff0c;来帮助企业实现数据化运营、支持智能决策、实现数据资产沉淀和增值、进行数据挖掘和预测分析、提高数据可读性和数据可视化程度等&#xff0c;从而提高企业的竞争…

【C++学习】STL容器——list

目录 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list 迭代器失效 二、list的模拟实现 2.1 模拟实现list 三、list和vector的对比…

Java版知识付费平台免费搭建 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台qt

&#xfeff;Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含&#xff1a;录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署&#xff0c;免费售…

CNN成长路:从AlexNet到EfficientNet(01)

一、说明 在 10年的深度学习中&#xff0c;进步是多么迅速&#xff01;早在 2012 年&#xff0c;Alexnet 在 ImageNet 上的准确率就达到了 63.3% 的 Top-1。现在&#xff0c;我们超过90%的EfficientNet架构和师生训练&#xff08;teacher-student&#xff09;。 如果我们在 Ima…

【Kubernetes部署篇】基于Ubuntu20.04操作系统搭建K8S1.23版本集群

文章目录 一、集群架构规划信息二、系统初始化准备(所有节点同步操作)三、安装kubeadm(所有节点同步操作)四、初始化K8S集群(master节点操作)五、添加Node节点到K8S集群中六、安装Calico网络插件七、测试CoreDNS可用性 一、集群架构规划信息 pod网段&#xff1a;10.244.0.0/16…

HTTP——九、基于HTTP的功能追加协议

HTTP 一、基于HTTP的协议二、消除HTTP瓶颈的SPDY1、HTTP的瓶颈Ajax 的解决方法Comet 的解决方法SPDY的目标 2、SPDY的设计与功能3、SPDY消除 Web 瓶颈了吗 三、使用浏览器进行全双工通信的WebSocket1、WebSocket 的设计与功能2、WebSocket协议 四、期盼已久的 HTTP/2.01、HTTP/…

卡尔曼滤波 | Matlab实现无迹kalman滤波仿真

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 卡尔曼滤波 | Matlab实现无迹kalman滤波仿真 研究内容 无迹kalman滤波(UKF)不是采用的将非线性函数线性化的做法。无迹kalman仍然采用的是线性kalman滤波的架构,对于一步预测方程,使用无迹变换(UT)来…