二.吊打面试官系列-数据库优化-Explain索引分析

news2024/11/28 0:52:13

1.如何定位慢SQL

我们知道数据库瓶颈80%都在查询上,数据库优化有一个比较重要的环节就是定位系统中的慢SQL,那么我们如何快速定位到哪些查询语句比较耗时呢?Mysql有自己的慢SQL定位功能

MySQL的慢查询日志,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过 long-query_time值的SQL,则会被记录到慢查询日志中。 long_query_time的默认值为 10,意思是运行10秒以上(不含10秒)的语句,认为是超出了我们的最大忍耐时间值。

命令备注
show status like ‘slow_queries’查看慢查询数量
show variables like ‘long_query_time’可以显示当前慢查询时间 , 默认阈值 10s
set long_query_time=1可以修改慢查询时间 , 可以通过my.ini永久修改
show variables like ‘%slow_query_log%’查看慢查询的日志路径
SET GLOBAL slow_query_log = 1开启慢查询日志
SET GLOBAL slow_query_log_file=‘路径\slow.log’指定慢查询日志文件
set global log_output=‘TABLE’把慢SQL输出到table
select * from mysql.slow_log查看日志内容

通过 show variables like ‘%slow_query_log% 查看慢日志是否开启以及可以看到日志存储位置,如果未开启使用SET GLOBAL slow_query_log = 1来开启

在这里插入图片描述

慢SQL记录默认执行时长为10S+的SQL,通过set long_query_time=1来修改慢SQL的时间。 此外还可以通过set global log_output=‘TABLE’来把慢SQL记录到Table中,通过SELECT *,CONVERT( sql_text USING utf8) AS text_data from mysql.slow_log来查看,这样就可以快速定位到慢SQL

在这里插入图片描述
上面的命令都是临时的,重启Mysql后就会失效,如果需要永久修改需要修改my.ini

[mysqld]
slow_query_log=ON # 开启慢查询日志的开关
slow_query_log_file=/var/lib/mysql/atguigu-slow.log #慢查询日志的目录和文件名信息
long_query_time=3 #设置慢查询的闽值为3秒,超出此设定值的SQL即被记录到慢查询日志
log_output=FILE

除此之外我们还可以通过三方工具来监控慢SQL,比如:Druid连接池的SQL监控
在这里插入图片描述

定位到慢SQL之后我们就需要去优化它,SQL优化的维度有很多,比如:

  • SQL是否太复杂,或者JOIN表太多,子查询太多:这种情况需要进行SQL简化,可以通过SQL拆解把一条SQL拆成多条SQL,或者通过冗余字段来减少JOIN。
  • 是不是数据量太大:如果是表数据量太大,那么需要考虑拆表,可以考虑垂直拆分或者水平拆分来减少表的数据量提高查询速度
  • 如果是对于报表类的查询最好是做统计表+定时结算的方式,不要直接查大表
  • 还有一个很重要的维度就是索引优化,500W的数据如果把索引优化好查询一般不会有大的问题

2.使用explain分析SQL

Explain用来分析SELECT查询语句,开发人员可以通过分析Explain结果来优化查询语句。通过explain命令我们可以学习到该条SQL是如何执行的,随后解析explain的结果可以帮助我们使用更好的索引,最终来优化它!通过explain命令我们可以知道以下信息:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。如下,我们在 select 语句前面加上explain 就可以看到SQL有没有用到索引

在这里插入图片描述

ID列

id列的编号是 select 的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的。id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

select_type列

select_type 表示对应行是简单还是复杂的查询。

  • simple:代表一个简单的查询,没有连表的情况

  • primary:SQL的主查询,如:复杂查询中最外层的 select

  • subquery:包含在 select 中的子查询(不在 from 子句中)如:EXPLAIN select id,(select name from t_user where id = 1) from t_user
    在这里插入图片描述

  • derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)

  • union:在有union连表查询的时候会出现 如:explain select 1 union all select 2;
    在这里插入图片描述

table列

代表的是当前访问的是哪个表

partitions列

分区,如果查询是基于分区表的话,会显示查询将访问的分区。分区用的很少

type列

这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围,依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL 一般来说,得保证查询达到range级别,最好达到ref

const, system:const是常量的意思,Mysql能对查询的某部分进行优化并将其转化成一个常量,用于 primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。system是const的特例,表里只有一条元组匹配时为system.案例如下:
explain select * from t_user where id = 1
在这里插入图片描述

eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在 const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。多出现于外键连表的查询中案例: explain select * from t_user u join t_dept d on u.dept_id = d.id
在这里插入图片描述

ref:相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀的情况,索引要和某个值相比较,可能会找到多个符合条件的行。案例如:explain select * from t_user where name = "zs"

在这里插入图片描述

range:范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。案例如:explain select * from t_user where id > 1

在这里插入图片描述

index扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接对索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些。案例如:explain select name from t_user

在这里插入图片描述

all:即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。
在这里插入图片描述

possible_keys 列

该列展示的是当前SQL可以选择的索引列,如果为null那么需要检查wehre后面的条件列是否有可选择的索引,案例 explain select * from t_user where name = "zs" and id = 1
在这里插入图片描述
可以选择的索引有3个 :PRIMARY , index_name_age , name ,Mysql选择了主键索引。

key 列

这一列显示mysql实际采用哪个索引来优化对该表的访问。如果没有使用索引,则该列是 NULL。

key_len列

这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。 比如:
在这里插入图片描述
key_len为8,因为Mysql使用了主键列,主键列是BigInt类型,这种类型占8个字节。

ref列

显示索引的哪一列被使用了,如果有可能是一个常数,哪些列或const(常量)被用于查询索引列上的,比如:explain select * from t_user u join t_dept d on u.dept_id = d.id
在这里插入图片描述

rows列

这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。

Extra列

这一列展示的是额外信息。常见的重要值如下:

  • Using index:表示相应的select操作用使用覆盖索引,避免访问了表的数据行,案例:explain select name from t_user
    在这里插入图片描述
    因为index_name这个索引中就包含了查询的name列,所以不用回表了

  • Using where:使用 where 语句来处理结果,并未使用到索引,需要优化 案例:explain select * from t_user where age = 11 这里看得出没有使用任何索引
    在这里插入图片描述

  • Using index condition:是 MySQL 查询执行计划中的一个输出,它表示 MySQL 优化器决定使用“索引条件推送”优化技术来执行查询。索引条件推送 (Index Condition Pushdown, ICP): 这是一个查询优化技术,允许 MySQL 将部分 WHERE 子句的条件下推到存储引擎层,使其可以在读取索引条目时直接评估这些条件。这可以减少不必要的数据读取,从而提高查询性能。案例explain select age from t_user where username = "zs" and name like "z%"
    在这里插入图片描述

  • Using temporary:使用了临时表保存中间结果,mysql在查询结果排序时使用临时表。常见于排序order by和分组查询group by,案例:explain select DISTINCT(name) from t_user
    在这里插入图片描述
    name列没有索引,那么在去重的时候会使用一个临时表来存储name列的值然后去重。如果给name列创建索引那么就会 : using index 在索引中去重。

  • Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。案例explain select * from t_user order by age
    在这里插入图片描述

  • Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段时.案例explain select max(id) from t_user
    在这里插入图片描述

3.怎么选择索引列

这里我们需要一个常识,索引就是以空间换时间的打法,索引本身会占用磁盘空间,且索引会降低DML操作(增删改)的性能,当我们对数据发生写操作索引也需要跟着修改,所以索引不是越多越好,而是要找到过滤数据最有效的那个列来创建索引,或者结合业务场景来设计索引,那么什么样的列适合创建索引呢

  1. 不会出现在WHERE,ORDER BY, GROUP BY子句中字段不该创建索引
    因为意义不大,这样的列即使创建了索引也大概率不会用到,反而增加了磁盘开销和维护成本
  2. 唯一性太差(离散度)的字段不适合单独创建索引
    比如:状态,性别这种字段,假如我有1千万数据,对于性别最多过滤一般,剩下的数据量依然很大,所以这种字段创建索引没有太大意义。
  3. 更新非常频繁的字段不适合创建索引
    因为字段值修改索引也要跟着修改,这样反而增加了索引维护成本会导致性能变差
  4. 对于记录数较少的表不适合创建索引
    表数据少创建索引可能并不会带来明显的性能提升。相反,由于索引本身也需要存储和管理,因此可能会增加额外的开销。

4.索引失效的情况

在 MySQL 中,索引虽然能极大地提高查询性能,但在某些情况下,索引可能不会被优化器使用,即索引失效。以下是导致 MySQL 索引失效的一些常见情况:

  1. 使用了函数或表达式
    当在 WHERE 子句中对索引列使用函数或表达式时,MySQL 通常无法使用该索引。例如:SELECT * FROM users WHERE YEAR(create_date) = 2023; 在这个例子中,YEAR() 函数导致 create_date 列上的索引失效。因为B+tree的节点上存储的是一个确切的值,它无法和 函数计算过的不确定值进行比较

  2. 类型不一致导致隐式类型转换
    当查询条件中的数据类型与索引列的数据类型不一致,并且 MySQL 需要进行隐式类型转换时,索引可能失效。例如:SELECT * FROM users WHERE phone_number = '1234567890';如果 phone_number 列是整数类型,而查询中使用了字符串字面量,MySQL 可能需要进行类型转换,从而用到转换函数,从而导致索引失效

  3. 使用了 OR 连接的条件
    在某些情况下,使用 OR 连接的条件可能导致索引失效,尤其是当 OR 连接的列不在同一个索引中时。比如:SELECT * FROM users WHERE name = 'John' OR email = 'john@example.com';如果 name 和 email 不在同一个索引中,MySQL 可能无法使用索引来优化这个查询。

  4. LIKE 查询以通配符开头
    当使用 LIKE 查询时,如果搜索模式以通配符 % 开头,MySQL 通常无法使用该列的索引,比如:SELECT * FROM users WHERE name LIKE '%Smith';因为左边的’%'代表了一个不确定的值,无法和索引进行比较,如果是’Smith%'这可以使用到索引,因为可以向左匹配

  5. 不等于操作
    使用 != 或 <> 进行不等于操作时,MySQL 通常不会使用索引,因为它需要扫描全表来找到不等于指定值的记录。

  6. IS NULL 或 IS NOT NUL
    在某些情况下,对索引列使用 IS NULL 或 IS NOT NULL 条件可能不会导致索引被使用,尤其是当表中包含大量 NULL 值时

  7. Mysql优化器决定不使用索引
    及时可以使用索引,如果mysql估计使用全表扫描要比使用索引快,则不使用索引,比如表里面只有一条记录

为了避免索引失效,你应该:

  • 确保查询条件与索引列的数据类型和结构相匹配。
  • 仔细选择和设计索引,包括复合索引的列顺序。
  • 定期更新统计信息,以确保优化器做出正确的决策。
  • 使用 EXPLAIN 语句来分析查询的执行计划,检查是否使用了预期的索引。

文章就先写到这把,拿去面试差不多也够用了,如果文章对你有所帮助请给个好评哦!!!

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

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

相关文章

Postman 环境变量配置初始调用登录脚本赋值Token

效果 新建环境 切换 Environments 标签下 点击上面加号增加环境变量 使用环境变量 使用{{变量名}}引用变量使用 Pre-request Script 全局 一般授权接口都需要再调用接口前&#xff0c;进行登录授权&#xff0c;这里使用了全局的请求前脚本调用。 脚本示例 // 基础地址 var…

【火猫TV】NBA:赛季数据王总结,国王双雄爆冷入选

NBA常规赛已经全部结束,各项数据王诞生,我们发现不少新人球星开始挑大梁,他们用出色的发挥证明了自己的实力。下面,为大家简单盘点下各项数据的最佳球员! 得分王:东契奇(场均33.9分) 本赛季独行侠低开高走,东契奇保持了出色发挥,他场均贡献33.9分,比第二的字母哥场均多出3.5分…

CAN网络管理(网络节点)

什么是CAN的网络节点 网络节点是指连接到CAN总线上的设备或模块,每个网络节点都具有唯一的标识符,称为节点ID,用于在CAN总线上进行通信和识别。 如何判断CAN的网络节点是多少 可以根据DBC来定义查看, 以ADCU为例,域控作为主节点,一般外部的像雷达,camera的数据都是向…

Tomcat下载配置地址

IntelliJ IDEA是一个强大的集成开发环境&#xff0c;能够大大简化Java应用程序的开发和部署过程。而Tomcat作为一个流行的Java Web服务器&#xff0c;其与IntelliJ IDEA的整合能够提供便捷的开发环境&#xff0c;让开发人员更专注于代码的创作与优化。 在配置IntelliJ IDEA以使…

鸿蒙应用开发之滑动选择组件

前面学习了下拉选择菜单组件,现在来学习滑动选择组件,它是提供快速调节设置值,如音量调节、亮度调节等应用场景。也就是说,这个组件可以通过滑动条来设置对应的数值,而不需要用户手动输入数字。 比如像下面的界面: 可以用手滑动上面的滑块,就可以调节对应的数字。这个组…

OpenHarmony轻量系统开发【7】驱动之I2C显示OLED屏幕

7.1实验效果 Hispark WiFi开发套件又提供一个oled屏幕&#xff0c;但是鸿蒙源码中没有这个屏幕的驱动&#xff0c;我们需要自己去移植。 以下是移植效果&#xff1a; 接口&#xff1a;I2C 使用引脚&#xff1a;HI_IO_NAME_GPIO_13 、 HI_IO_NAME_GPIO_14 7.2代码 这里我直…

Webrtc 信令服务器实现

webrtc建联流程图 由上图可知&#xff0c;所谓的信令服务器其实就是将peer的offer/candidate/answer传给对端而已。这样的话实现方式就有很多种了&#xff0c;目前普遍的方式HTTP/HTTPS&#xff0c;WS/WSS。像webrtc-demo-peerconnection就是实现HTTP这种方式。本文使用WS&…

微信小程序订阅消息授权弹窗问题整理

文档 小程序订阅消息&#xff08;用户通过弹窗订阅&#xff09;开发指南 | 微信开放文档 1.报错10004 errCode: 10004errMsg: "requestSubscribeMessage:fail Invalid template id" 真机调试也不行 wx.requestSubscribeMessage({tmplIds: result,// 用户同意与否…

天池酒瓶瑕疵检测数据集分析及完整baseline

以下内容为还没思路的小伙伴牵个头提供一个demo,大佬勿喷,线上成绩0.7,留空间给小伙伴们发挥自己的力量 ps:markdown不怎么熟悉,代码中如有明显缩进问题,自行斟酌改正,编辑好几次都改不过来,请原谅.... 数据分析瑕疵大类: 瓶盖瑕疵、标贴瑕疵、喷码瑕疵、瓶身瑕疵、酒液瑕疵瑕…

【canvas】canvas基础使用(九):文本绘制

简言 canvas除了能够绘制图形外&#xff0c;也可以绘制文本。 绘制文本 fillText() 填充文本 CanvasRenderingContext2D 对象的方法 fillText() 是 Canvas 2D API 的一部分&#xff0c;它在指定的坐标上绘制文本字符串&#xff0c;并使用当前的 fillStyle 对其进行填充。存…

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写教程

原文链接&#xff1a;ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601506&idx2&sn5dae3fdc3e188e81b8a6142c5ab8c994&chksmfa820c85cdf58593356482880998fc6eb98e6889b261bf62…

如何解决DDoS攻击?

DDoS攻击&#xff08;分布式拒绝服务攻击&#xff09;是一种恶意利用多台傀儡机协同发起大规模网络流量&#xff0c;旨在压垮目标系统或网络资源&#xff0c;使其无法正常服务的网络攻击手段。由于现代计算机和网络性能的提升&#xff0c;单点发起的DoS攻击已难以奏效&#xff…

基于ssm缪斯乐器购物网站的设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本缪斯乐器购物网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

DNF手游攻略:萌新入坑大全!

玩DNF手游国服已经正式定档&#xff0c;离上线已经越来越近了&#xff0c;很多小伙伴对于装备打造以及附魔还不是特别了解。如果你还不知道装备要怎么附魔&#xff0c;不要担心&#xff0c;本篇攻略将为你全面解析全职业过渡和毕业附魔推荐。 ​ 一、物理职业附魔推荐 1. 武器…

知道XRD标准品PDF卡片号,如何直接导出标准物质数据,简单快速一分钟完成(附jade下载安装方法)

知道XRD标准品PDF卡片号&#xff0c;如何直接导出标准物质数据&#xff08;附jade下载安装方法&#xff09; 网上找到的方法都是先检索再导出&#xff0c;我的样品根本检索不到&#xff0c;但是根据参考文献知道了自己的pdf卡片号&#xff0c;可通过jade直接导出数据 1.请安装…

【kafka】安装

也是第二次安装&#xff0c;蛮记录一下 1.安装kafka之前需要先完成zookeeper的安装 【zookeeper】安装 2. Apache Kafka官网下载 3. 解压完成后修改server.properties配置文件 修改日志文件存放路径 查看与zookeeper连接的端口是否和zookeeper服务所在的端口一致 &#xf…

在vue中发现一个prop新的写法在官方文档没有,查百度不行,还有什么其他方法排查不

先看图&#xff0c;最近在接手一个同事的代码&#xff0c;发现prop有这样的写法&#xff1a; 我自己查了官网&#xff0c;以及百度都没有找到这种写法。这时我灵机一动&#xff0c;想到一个方法&#xff0c;vscode有内置的typesscript&#xff0c;自然有prop类型推断&#xff0…

【数据结构】树与二叉树、树与森林部分习题以及算法设计例题 2

目录 【数据结构】树与二叉树、树与森林部分习题以及算法设计例题一、交换二叉树每个结点的左右孩子Swap 函数&#xff08;先序遍历&#xff09;&#xff1a;Swap 函数&#xff08;中序遍历&#xff09; 不可行&#xff1a;Swap 函数&#xff08;后序遍历&#xff09;&#xff…

Java小白教学—五千字带你了解多线程机制及线程安全问题

基础概念 &#x1f4d6; 问题一 : 什么是线程&#xff1f;线程和程序、进程有什么区别&#xff1f; 程序&#xff1a;为实现某种功能&#xff0c;使用计算机语言编写的一系列指令的集合。 指的是静态的代码&#xff08;例如安装在电脑上的那些文件&#xff09; 进程&#xff…

由于找不到msvcr120.dll,无法继续执行代码的详细处理方法,教你快修复msvcr120.dll

DLL文件&#xff0c;全称动态链接库文件&#xff0c;在计算机系统中具有重要作用。其中&#xff0c;msvcr120.dll是一个常见的DLL文件&#xff0c;它关联了许多程序和应用的正常运行。本指南将深入解释 msvcr120.dll文件的功能&#xff0c;并阐述如果缺少该文件会引起什么样的问…