详解MySQL慢SQL定位、分析

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 1.概述解决慢SQL的问题无非3步:定位慢SQL分析慢SQL优化慢SQL本文将按顺序介绍前两步该怎么做,第三步将会在后续的文章中详细讨论。

1.概述

解决慢SQL的问题无非3步:

  • 定位慢SQL
  • 分析慢SQL
  • 优化慢SQL

本文将按顺序介绍前两步该怎么做,第三步将会在后续的文章中详细讨论。

2.慢SQL定位

mysql自带了慢sql日志这个功能,会记录下慢SQL,以下是使用方法。

开启慢sql统计:

SET GLOBAL slow_query_log = on;   //开启慢sql统计开关

设置判断为慢sql的阈值(单位秒):


SET GLOBAL long_query_time = 1;

设置日志位置:


set global slow_query_log_file="D:\\slow.log";

我在sys_user这个自己建的表里插入了一百万条数据,简单执行一个数量统计的SQL就会触发慢sql的阈值被记录下来:

9bff0bbaebc142c0af0a937e878a6281.png

3.SQL性能分析

3.1.例子

三张表,course(课程表)、teacher(教师表)、teacherCard(教师信息表),表关系如下:

898980645d3f4398805645797051afad.png

建表语句

create table course_info
(
    cid   bigint primary key,
    name varchar(255),
    _desc varchar(255)
) engine = innodb
  default charset = utf8;
create table teacher_info
(
    tid   bigint primary key,
    name varchar(255),
    _desc varchar(255)
) engine = innodb
  default charset = utf8;
create table school_timetable
(
    id   bigint primary key,
    tid bigint,
    cid bigint
)engine = innodb
 default charset = utf8;

数据:

insert into course_info value(1,'计算机组成原理','介绍计算机的体系结构');
insert into course_info value(2,'数据结构','介绍如何高效的组织数据');
insert into course_info value(3,'操作系统','介绍如何管理调度计算机的资源');
insert into course_info value(4,'JAVA','天下第一的编程语言');
insert into teacher_info value(1,'冯诺依曼','现代计算机之父');
insert into teacher_info value(2,'图灵','计算机科学之父');
insert into teacher_info value(3,'林纳斯托瓦兹','Linux之父');
insert into teacher_info value(4,'詹姆斯高斯林','java之父');
insert into school_timetable value(1,1,1);
insert into school_timetable value(2,2,2);
insert into school_timetable value(3,3,3);
insert into school_timetable value(4,4,4);

3.2.SQL性能分析

可以通过explain关键字来对SQL进行性能分析,MySQL的EXPLAIN是一个查询优化工具,用于分析查询语句的执行计划,它会清晰的展示MySQL将会如何执行某个查询语句,包括执行的步骤、执行顺序、使用的索引、访问表的方式、以及如何连接表等。

以这条SQL为例:

explain select * from teacher_info;

我们能得到以下结果集:

bebd2192779e47479538fb8878020513.png

结果集包含以下参数:


参数 作用

id 编号

select_type 查询类型

table 表

type 连接类型

possible_keys 预测用到的索引

key 实际用到的索引

key_len 实际用到的索引长度

ref 本次查询引用了哪些字段,哪些数据进行查找

rows 完成当前查询,预计所要读取的行数

Extra 额外的信息

下面对一些核心参数进行一下详细介绍。

3.3.参数说明

3.3.1.id

每条SQL都会有个id用来决定执行顺序,

id值同则由大向小降序执行。

explain
select * from teacher_info
UNION
SELECT * FROM school_timetable

f20e4b1cf01d4c98a6bcf03c5b230b2c.png

id值相同则由上往下顺序执行。

explain
select * from teacher_info
left join school_timetable on teacher_info.tid=school_timetable.tid
left join course_info on course_info.cid=school_timetable.cid;

0d603b7d86304cebb45a4660acbc9141.png

3.3.2.select_type

select_type,查询类型,这个参数会有点绕,但是其实理解即可,它在调优里用处并不大。

e549279f0e674c9ca274d7c364c8372d.png

3.3.3.key_len

key_len,实际用到的索引长度,可以用来辅助判断复合索引内生效的部分。

假设我建立了一个复合索引:

CREATE INDEX cid_tid ON school_timetable (cid, tid)

索引全部生效:

explain select * from school_timetable where cid=4 and tid=4


1f79263d2e4745e68c86351c520c0f8b.png

部分索引生效:

explain select * from school_timetable where cid=4

7f0cc837c0894e5787a38819cbf994ba.png

3.3.4.rows

完成当前查询,预计所要读取的行数,是个估计值,不准确。

explain select * from school_timetable where cid<4

3.3.5.type

type,查找方式,查询操作的访问类型,它描述了 MySQL 在执行查询时使用的访问方法。

整个执行计划中重中之重的一个参数,整个SQL优化就是围绕此参数进行优化。

常用的访问方法按速度排:

  • system:系统表的查询,仅返回一行结果,速度最快。


const:常量查询,这种类型的查询是基于常量条件进行的,例如主键或唯一索引的查询,MySQL 在查询过程中已经确定只有一条匹配的结果。


eq_ref:唯一索引访问,通过唯一索引查找。这种类型的查询通常用于使用主键或唯一索引进行关联查询,每个索引值只有一条匹配的结果。


ref:非唯一索引访问,通过非唯一索引查找。这种类型的查询通常用于使用非唯一索引进行查询,每个索引值可能有多条匹配的结果。


range:范围扫描,对索引使用了范围查找,例如使用 BETWEEN、<、> 等操作符进行的查询。


index:索引扫描,MySQL 使用非唯一索引进行扫描,表示在索引列上进行了查找。


ALL:全表扫描,MySQL 将对表中的每一行进行遍历。这种类型的查询通常发生在没有使用索引或无法使用索引的情况下,性能较差。


在实际工程中,前三种情况是很难达到的,基本没有什么适用场景,所以我们需要尽力保障能达到ref、range或者index,也就是至少要保证索引是有效的。

以下是前文表中出现以上情况的示例,由于system和eq_ref比较难造,暂时不包括:

const:

c4a8b826ea114dcb9d45c9f249d6065e.png

ref:

b0d92624f55b49039569010aaba3f196.png

index:

f5121ca7782840a696543c9358145e25.png

range:

5e0fedf293d047b69327600cb1e2cb19.png

3.3.6.extra

这个字段表示查询后是否还要进行额外的操作再生成结果集。常见的值如下:


Using index: 表示查询使用了覆盖索引,即查询的数据可以直接从索引中获取,而无需进一步访问表数据。


Using where: 表示查询使用了 WHERE 条件进行过滤。


Using temporary: 表示查询需要创建临时表来处理结果集,通常发生在需要进行排序、分组或多表连接的情况下。


Using filesort: 表示查询需要进行排序操作,MySQL 无法使用索引进行排序,因此需要额外的文件排序操作。


Using index condition: 表示查询使用了索引条件进行过滤。


Using join buffer: 表示查询使用了连接缓冲区。


Distinct: 表示查询使用了 DISTINCT 关键字进行去重。


Full scan on NULL key: 表示在索引上执行全表扫描,但索引键值为空。


Range checked for each record: 表示对每条记录都进行了范围检查。


Using index for group-by: 表示查询使用了索引来进行分组操作。


Using index for order by: 表示查询使用了索引来进行排序操作。


Using index condition; Using where: 表示查询同时使用了索引条件和 WHERE 条件。


对于 SQL 调优来说,extra 字段是非常重要的。它提供了关于查询执行计划中的额外信息,可以帮助我们识别查询的性能瓶颈和优化的方向。


通过分析 extra 字段,我们可以判断以下情况:


是否使用了索引:Using index 表示查询使用了覆盖索引,可以避免访问表数据,提高查询性能。如果没有使用索引,可能需要考虑添加适当的索引来优化查询。


是否进行了排序:Using filesort 表示需要额外的文件排序操作,这可能导致性能下降。如果频繁出现文件排序,可能需要考虑优化查询或调整索引。


是否创建了临时表:Using temporary 表示需要创建临时表来处理结果集,可能会影响性能。需要审查查询语句并考虑是否可以避免使用临时表。


是否进行了全表扫描:Using index 表示使用了索引,而 Using index; Using where 表示同时使用了索引和 WHERE 条件进行过滤。如果出现 Using index 之外的情况,可能需要优化查询或调整索引以避免全表扫描。


是否使用了连接缓冲区:Using join buffer 表示使用了连接缓冲区,可能会影响查询性能。需要审查查询语句并考虑是否可以优化连接操作。


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
22
分享
相关文章
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
【YashanDB知识库】如何将mysql含有group by的SQL转换成崖山支持的SQL
本文探讨了在YashanDB(崖山数据库)中执行某些SQL语句时出现的报错问题,对比了MySQL的成功执行结果。问题源于SQL-92标准对非聚合列的严格限制,要求这些列必须出现在GROUP BY子句中,而SQL:1999及更高版本允许非聚合列直接出现在选择列中。YashanDB和Oracle遵循SQL-92标准,因此会报错。文章提供了两种解决方法:使用聚合函数处理非聚合列,或将GROUP BY与ORDER BY拆分为两层查询。最后总结指出,SQL-92标准更为严谨合理,建议开发者遵循此规范以避免潜在问题。
无缝集成 MySQL,解锁秒级 OLAP 分析性能极限,完成任务可领取三合一数据线!
通过 AnalyticDB MySQL 版、DMS、DTS 和 RDS MySQL 版协同工作,解决大规模业务数据统计难题,参与活动完成任务即可领取三合一数据线(限量200个),还有机会抽取蓝牙音箱大奖!
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
84 9
MySQL的架构与SQL语句执行过程
MySQL架构分为Server层和存储引擎层,具有高度灵活性和可扩展性。Server层包括连接器、查询缓存(MySQL 8.0已移除)、分析器、优化器和执行器,负责处理SQL语句;存储引擎层负责数据的存储和读取,常见引擎有InnoDB、MyISAM和Memory。SQL执行过程涉及连接、解析、优化、执行和结果返回等步骤,本文详细讲解了一条SQL语句的完整执行过程。
106 3
【YashanDB 知识库】如何将 mysql 含有 group by 的 SQL 转换成崖山支持的 SQL
在崖山数据库中执行某些 SQL 语句时出现报错(YAS-04316 not a single-group group function),而这些语句在 MySQL 中能成功执行。原因是崖山遵循 SQL-92 标准,不允许选择列表中包含未在 GROUP BY 子句中指定的非聚合列,而 MySQL 默认允许这种操作。解决办法包括:使用聚合函数处理非聚合列或拆分查询为两层,先进行 GROUP BY 再排序。总结来说,SQL-92 更严格,确保数据一致性,MySQL 在 5.7 及以上版本也默认遵循此标准。
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
289 82

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等