数据库优化——慢查询MySQL定位优化流程

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 如何定位并优化慢查询SQL?如何使用慢查询日志?本文带来慢查询例子演示,新手都能看懂!那查询语句慢怎么办?explain带你分析sql执行计划!当主键索引、唯一索引、普通索引都存在,查询优化器如何选择?本文带你一探究竟!

继前篇博文看了这么多,终于理解了MySQL索引之后,给大家再来一篇日常开发需要用到的优化技巧。

1.如何定位并优化慢查询SQL?

一般有3个思考方向
1.根据慢日志定位慢查询sql
2.使用explain等工具分析sql执行计划
3.修改sql或者尽量让sql走索引

2.如何使用慢查询日志?

先给出步骤,后面说明
有3个步骤
1.开启慢查询日志

  首先开启慢查询日志,由参数slow_query_log决定是否开启,在MySQL命令行下输入下面的命令:

set global slow_query_log=on;

默认环境下,慢查询日志是关闭的,所以这里开启。

2.设置慢查询阈值

set global long_query_time=1;

  只要你的SQL实际执行时间超过了这个阈值,就会被记录到慢查询日志里面。这个阈值默认是10s,线上业务一般建议把long_query_time设置为1s,如果某个业务的MySQL要求比较高的QPS,可设置慢查询为0.1s。发现慢查询及时优化或者提醒开发改写。一般测试环境建议long_query_time设置的阀值比生产环境的小,比如生产环境是1s,则测试环境建议配置成0.5s。便于在测试环境及时发现一些效率的SQL

  甚至某些重要业务测试环境long_query_time可以设置为0,以便记录所有语句。并留意慢查询日志的输出,上线前的功能测试完成后,分析慢查询日志每类语句的输出,重点关注Rows_examined(语句执行期间从存储引擎读取的行数),提前优化。

3.确定慢查询日志的文件名和路径

show global variables like 'slow_query_log_file'

在这里插入图片描述
结果会发现慢日志默认路径就是MySQL的数据目录,我们可以来看一下MySQL数据目录

 show global variables like 'datadir';

在这里插入图片描述
不用关注这里为什么不是MySQL 8.0,这和版本没什么关系的。

来,直接上菜,干巴巴的定义我自己都看不下去

我们先来查看一下变量,我框出了需要注意的点
查询带有quer的相关变量

show global variables like '%quer%';

这里设置慢查询阈值为1s

set global long_query_time=1;

可以看到已经修改过来了

  但是重启mysql客户端设置和统计慢查询日志条数就会清零,即所有配置修改会还原

  命令修改配置之后,在命令行net stop mysql关闭MySQL服务,再net start mysql开启MySQL服务,接着执行show global variables like '%quer%';会发现配置还原了。

  在配置文件修改才能永久改变,否则重启数据库就还原了

3.慢查询例子演示,新手都能看懂

数据表结构,偷懒没写comment

CREATE TABLE `person_info_large` (  
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,  
    `account` VARCHAR (10),   
    `name` VARCHAR (20),  
    `area` VARCHAR (20),  
    `title` VARCHAR (20), 
    `motto` VARCHAR (50),
    PRIMARY KEY (`id`),  
    UNIQUE(`account`),
    KEY `index_area_title`(`area`,`title`) 
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8

这里的数据是200W条。请注意表结构,记住哪几个字段有索引即可,后续围绕这个表进行分析。

这个3.36s并不是实际执行时间,实际执行时间得去慢查询日志去看Query_time参数

  可以看到Query_time: 6.337729s,超过了1s,所以会被记录,一个select语句查询这么久,简直无法忍受。

图中其他的参数解释如下:
Time:慢查询发生的时间
Query_time:查询时间
Lock_time:等待锁表的时间
Rows_sent:语句返回的行数
Rows_exanined:语句执行期间从存储引擎读取的行数

  上面这种方式是用系统自带的慢查询日志查看的,如果觉得系统自带的慢查询日志不方便查看,可以使用pt-query-digest或者mysqldumpslow等工具对慢查询日志进行分析。

  注意:有的慢查询正在执行,结果已经导致数据库负载过高,而由于慢查询还没执行完,因此慢查询日志看不到任何语句,此时可以使用show processlist命令查看正在执行的慢查询。show processlist显示哪些线程正在运行,如果有PROCESS权限,则可以看到所有线程。否则,只能看到当前会话线程。

4.查询语句慢怎么办?explain带你分析sql执行计划

根据上一节的表结构可以知道,account是添加了唯一索引的字段。explain分析一下执行计划。

  我们重点需要关注select_typetypepossible_keyskeyExtra这些列,我们来一一说明,看到select_type列,这里是SIMPLE简单查询,其他值下面给大家列出。

type列,这里是index,表示全索引扫描

  表格从上到下代表了sql查询性能从最优到最差,如果是type类型是all,说明sql语句需要优化。

注意:如果type = NULL,则表明个MySQL不用访问表或者索引,直接就能得到结果,比如explain select sum(1+2);

  possible_keys代表可能用到的索引列,key表示实际用到的索引列,以实际用到的索引列为准,这是查询优化器优化过后选择的,然后我们也可以根据实际情况强制使用我们自己的索引列来查询。

  Extra列,这里是Using index


  一定要注意,Extra中出现Using filesortUsing temporary代表MySQL根本不能使用索引,效率会受到严重影响,应当尽可能的去优化。

  出现Using filesort说明MySQL对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容,有索引就维护了B+树,数据本来就已经排好序了,这说明根本没有用到索引,而是数据读完之后再排序,可能在内存或者磁盘上排序。也有人将MySQL中无法利用索引的排序操作称为“文件排序”。

  出现Using temporary表示MySQL在对查询结果排序时使用临时表,常见于order by和分组查询group by

回到上一个话题,我们看到account是添加了唯一索引的字段。explain分析了执行计划后

直接按照account降序来查

查看慢查询日志发现,使用索引之后,查询200W条数据的速度快了2s

接着我们分析一下查询namesql执行计划

然后给name字段加上索引

加上索引之后,继续看看查询namesql执行计划

  对比一下前面name不加索引时的执行计划就会发现,加了索引后,typeALL全表扫描变成index索引扫描。order by并没有 using filesort,而是using index,这里B+树已经将这个非聚集索引的索引字段的值排好序了,而不是等到查询的时候再去排序。

  接着我们继续执行查询语句,此时name已经是添加了索引的。

  结果发现,name添加索引之前,降序查询name是花费6.337729s,添加索引之后,降序查询name花费了3.479827s,原因就是B+树的结果集已经是有序的了。

5.当主键索引、唯一索引、普通索引都存在,查询优化器如何选择?

  查询一下数据的条数,这里count(id),分析一下sql执行计划

  这里实际使用的索引是account唯一索引。

  分析一下:实际使用哪个索引是查询优化器决定的,B+树的叶子结点就是链表结构,遍历链表就可以统计数量,但是这张表,有主键索引、唯一索引、普通索引,优化器选择了account这个唯一索引,这肯定不会使用主键索引,因为主键索引是聚集索引,每个叶子包含具体的一个行记录(很多列的数据都在里面),而非聚集索引每个叶子只包含下一个主键索引的指针,很显然叶子结点包含的数据是越少越好,查询优化器就不会选择主键索引

  当然,也可以强制使用主键索引,然后分析sql执行计划

我们看一下优化器默认使用唯一索引大致执行时间676ms

强制使用主键索引大致执行时间779ms

  我们可以用force index强制指定索引,然后去分析执行计划看看哪个索引是更好的,因为查询优化器选择索引不一定是百分百准确的,具体情况可以根据实际场景分析来确定是否使用查询优化器选择的索引。



欢迎一键三连~



有问题请留言,大家一起探讨学习



----------------------Talk is cheap, show me the code-----------------------

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
关系型数据库 MySQL 分布式数据库
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
45 2
|
JavaScript 关系型数据库 MySQL
❤Nodejs 第六章(操作本地数据库前置知识优化)
【4月更文挑战第6天】本文介绍了Node.js操作本地数据库的前置配置和优化,包括处理接口跨域的CORS中间件,以及解析请求数据的body-parser、cookie-parser和multer。还讲解了与MySQL数据库交互的两种方式:`createPool`(适用于高并发,通过连接池管理连接)和`createConnection`(适用于低负载)。
19 0
|
5天前
|
SQL 存储 关系型数据库
数据库开发之mysql前言以及详细解析
数据库开发之mysql前言以及详细解析
14 0
|
2天前
|
SQL 关系型数据库 MySQL
不允许你不知道的 MySQL 优化实战(一)
不允许你不知道的 MySQL 优化实战(一)
10 2
|
2天前
|
缓存 NoSQL 关系型数据库
在Python Web开发过程中:数据库与缓存,MySQL和NoSQL数据库的主要差异是什么?
MySQL与NoSQL的主要区别在于数据结构、查询语言和可扩展性。MySQL是关系型数据库,依赖预定义的数据表结构,使用SQL进行复杂查询,适合垂直扩展。而NoSQL提供灵活的存储方式(如JSON、哈希表),无统一查询语言,支持横向扩展,适用于处理大规模、非结构化数据和高并发场景。选择哪种取决于应用需求、数据模型及扩展策略。
10 0
|
3天前
|
存储 缓存 关系型数据库
掌握MySQL数据库这些优化技巧,事半功倍!
掌握MySQL数据库这些优化技巧,事半功倍!
|
3天前
|
缓存 关系型数据库 MySQL
MySQL数据库优化技巧:提升性能的关键策略
索引是提高查询效率的关键。根据查询频率和条件,创建合适的索引能够加快查询速度。但要注意,过多的索引可能会增加写操作的开销,因此需要权衡。
|
4天前
|
SQL Oracle 关系型数据库
下次老板问你MySQL如何优化时,你可以这样说,老板默默给你加工资
现在进入国企或者事业单位做技术的网友越来越多了,随着去O的力度越来越大,很多国企单位都开始从Oracle向MySQL转移,相对于Oracle而言,MySQL最大的问题就是性能,所以,这个时候,在公司如果能够处理好MySQL的性能瓶颈,那么你也就很容易从人群中脱颖而出,受到老板的青睐。
22 1
|
9天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
10天前
|
SQL NoSQL 关系型数据库
初识MySQL数据库——“MySQL数据库”
初识MySQL数据库——“MySQL数据库”