MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)


Posted in MySQL onApril 09, 2022

1.概述

在应用系统开发过程中,由于初期数据量小,开发人员写SQL语句时更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,很多SQL语句开始逐渐显露出性能问题,对生产环境的影响也越来越大,此时这些有问题的SQL语句就成为整个系统性能的瓶颈,因此我们必须要对它们进行优化,该章节将详细介绍在MySQL中优化SQL语句的方法。

2.通过show status命令了解各种SQL的执行频率

MySQL客户端连接成功后,通过show [session|global]status命令可以提供服务器状态信息,也可以在操作系统上使用mysqladmin extended-status命令获得这些消息。show [session|global] status可以根据需要加上参数“session”或者“global”来显示session级(当前连接)的统计结果和global级(自数据库上次启动至今)的统计结果。如果不写,默认使用参数是“session”。
下面的命令显示了当前session中所有统计参数的值:

-- 查看会话所有统计的值
SHOW STATUS LIKE 'Com_%';
Or
SHOW SESSION STATUS LIKE 'Com_%';

MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)

下面的命令显示了当前global中所有统计参数的值:
-- 查看全局所有统计的值

SHOW GLOBAL STATUS LIKE 'Com_%';

MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)
Com_xxx表示每个xxx语句执行的次数,我们通常比较关心的是以下几个统计参数:
●Com_select:执行SELECT操作的次数,一次查询只累加1。
●Com_insert:执行INSERT操作的次数,对于批量插入的INSERT操作,只累加一次。
●Com_update:执行UPDATE操作的次数。
●Com_delete:执行DELETE操作的次数。
上面这些参数对于所有存储引擎的表操作都会进行累计。下面这几个参数只是针对InnoDB存储引擎的,累加的算法也略有不同。
●Innodb_rows_read:SELECT查询返回的行数。
●Innodb_rows_inserted:执行INSERT操作插入的行数。
●Innodb_rows_updated:执行UPDATE操作更新的行数。
●Innodb_rows_deleted:执行DELETE操作删除的行数。
通过以上几个参数,可以很容易地了解当前数据库的应用系统是以插入更新为主还是以查询操作为主,以及各种类型的SQL大致的执行比例是多少。对于更新操作的计数,是对执行次数的计数,不论提交还是回滚都会进行累加。
对于事务型的应用,通过Com_commit和Com_rollback可以了解事务提交和回滚的情况,对于回滚操作非常频繁的数据库,可能意味着应用编写存在问题。此外,以下几个参数便于用户了解数据库的基本情况。 
●Connections:试图连接MySQL服务器的次数。
●Uptime:服务器工作时间。
●Slow_queries:慢查询的次数。

3.定位执行效率较低的SQL语句

可以通过以下两种方式定位执行效率较低的SQL语句。
通过慢查询日志定位那些执行效率较低的SQL语句,用--log-slow-queries[=file_name]选项启动时,mysqld写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件。
慢查询日志在查询结束以后才纪录,所以在应用系统反映执行效率出现问题的时候查询慢查询日志并不能定位问题,可以使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看SQL的执行情况,同时对一些锁表操作进行优化。

4.通过EXPLAIN分析低效SQL的执行计划

通过定位执行效率较低的SQL语句后,可以通过EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序,比如想统计所有库存阶梯数量,需要关联goods_stock表和goods_stock_price表,并且对goods_stock_price.Qty字段做求和(sum)操作,相应 SQL 的执行计划如下:

EXPLAIN SELECT SUM(sp.Qty)
FROM goods_stock AS s LEFT JOIN goods_stock_price AS sp
ON s.ID=sp.GoodsStockID;

MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)

如上图所示每个列的简单解释如下:

●select_type:表示 SELECT 的类型,常见的取值有:
  ◎SIMPLE(简单表,即不使用表连接 或者子查询)。
  ◎PRIMARY(主查询,即外层的查询)、UNION(UNION 中的第二个或 者后面的查询语句)、◎SUBQUERY(子查询中的第一个SELECT)等。
●table:输出结果集的表。
●type:表示表的连接类型,性能由好到差的连接类型为:
  ◎system(表中仅有一行,即常量表)。
  ◎const(单表中最多有一个匹配行,例如primary key或者unique index)。
  ◎eq_ref(对于前面的每一行,在此表中只查询一条记录,简单来说,就是多表连接中使用primary key或者unique index)。
  ◎ref(与eq_ref类似,区别在于不是使用primary key或者unique index,而是使用普通的索引)。
  ◎ref_or_null(与ref类似,区别在于条件中包含对NULL的查询)。
  ◎index_merge(索引合并优化)。
  ◎unique_subquery(in的后面是一个查询主键字段的子查询)。
  ◎index_subquery(与unique_subquery类似,区别在于in的后面是查询非唯一索引字段的子查询)。
  ◎range(单表中的范围查询)。
  ◎index(对于前面的每一行,都通过查询索引来得到数据)。
  ◎all(对于前面的每一行,都通过全表扫描来得到数据)。
●possible_keys:表示查询时,可能使用的索引。
●key:表示实际使用的索引。
●key_len:索引字段的长度。
●rows:扫描行的数量。
●filtered:返回结果的行占需要读到的行(rows列的值)的百分比。
●Extra:执行情况的说明和描述。
  ◎Using index(此值表示mysql将使用覆盖索引,以避免访问表)。
  ◎Using where(mysql 将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引)。
  ◎Using temporary(mysql 对查询结果排序时会使用临时表)。
  ◎Using filesort(mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成)。
  ◎Range checked for each record(index map: N) (没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的)。

5.确定问题并采取相应的优化措施

经过以上定位步骤,我们基本就可以分析到问题出现的原因。此时我们可以根据情况采取相应的改进措施,进行优化提高语句执行效率。
在上面的例子中,已经可以确认是goods_stock是走主键索引的,但是对goods_stock_price子表的进行了全表扫描导致效率的不理想,那么应该对goods_stock_price表的GoodsStockID字段创建索引,具体命令如下:

-- 创建索引CREATE INDEX idx_stock_price_1 ON goods_stock_price (GoodsStockID);-- 附加删除跟查询索引语句ALTER TABLE goods_stock_price DROP INDEX idx_stock_price_1;SHOW INDEX FROM goods_stock_price;

创建索引后,我们再看一下这条语句的执行计划,具体如下:

EXPLAIN SELECT SUM(sp.Qty)
FROM goods_stock AS s LEFT JOIN goods_stock_price AS sp
ON s.ID=sp.GoodsStockID;

MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)
可以发现建立索引后对goods_stock_price子表需要扫描的行数明显减少(从 3 行减少到1行),可见索引的使用可以大大提高数据库的访问速度,尤其在表很庞大的时候这种优势更为明显。

参考文献:
深入浅出MySQL大全

MySQL 相关文章推荐
mysql对于模糊查询like的一些汇总
May 09 MySQL
mysql 8.0.24 安装配置方法图文教程
May 12 MySQL
MySQL 自定义变量的概念及特点
May 13 MySQL
MySql 8.0及对应驱动包匹配的注意点说明
Jun 23 MySQL
MySQL表类型 存储引擎 的选择
Nov 11 MySQL
mysql创建存储过程及函数详解
Dec 04 MySQL
SQL语句多表联合查询的方法示例
Apr 18 MySQL
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
Apr 20 MySQL
MySQL提取JSON字段数据实现查询
Apr 22 MySQL
手把手带你彻底卸载MySQL数据库
Jun 14 MySQL
MySQL8.0 Undo Tablespace管理详解
Jun 16 MySQL
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
Sep 23 MySQL
进阶篇之linux环境下安装MySQL数据库
MySQL的存储函数与存储过程的区别解析
Apr 08 #MySQL
MySQL数据库查询进阶之多表查询详解
MySQL中一条SQL查询语句是如何执行的
解决MySQL Varchar 类型尾部空格的问题
Apr 06 #MySQL
mysql的单列多值存储实例详解
Apr 05 #MySQL
详细聊一聊mysql的树形结构存储以及查询
You might like
php更改目录及子目录下所有的文件后缀扩展名的代码
2010/10/12 PHP
php中require和require_once的区别说明
2014/02/27 PHP
五款PHP代码重构工具推荐
2014/10/14 PHP
php给数组赋值的实例方法
2019/09/26 PHP
Laravel5.1框架路由分组用法实例分析
2020/01/04 PHP
js身份证验证超强脚本
2008/10/26 Javascript
jQuery Ajax之$.get()方法和$.post()方法
2009/10/12 Javascript
javascript完美拖拽的实现方法
2013/09/29 Javascript
JQuery限制复选框checkbox可选中个数的方法
2015/04/20 Javascript
Node.js编写组件的三种实现方式
2016/02/25 Javascript
JavaScript计算器网页版实现代码分享
2016/07/15 Javascript
JS判断form内所有表单是否为空的简单实例
2016/09/09 Javascript
在javaScript中检测数据类型的几种方式小结
2017/03/04 Javascript
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
Nuxt.js开启SSR渲染的教程详解
2018/11/30 Javascript
深入理解vue-class-component源码阅读
2019/02/18 Javascript
[02:03]永远的信仰DOTA2 中国军团历届国际邀请赛回顾
2016/06/26 DOTA
Python获取Windows或Linux主机名称通用函数分享
2014/11/22 Python
Python字符串特性及常用字符串方法的简单笔记
2016/01/04 Python
Django使用httpresponse返回用户头像实例代码
2018/01/26 Python
python 将大文件切分为多个小文件的实例
2019/01/14 Python
Python获取网段内ping通IP的方法
2019/01/31 Python
python实现画出e指数函数的图像
2019/11/21 Python
基于spring boot 日志(logback)报错的解决方式
2020/02/20 Python
Python实现密钥密码(加解密)实例详解
2020/04/26 Python
如何使用PyCharm将代码上传到GitHub上(图文详解)
2020/04/27 Python
Python Charles抓包配置实现流程图解
2020/09/29 Python
中间件分为哪几类
2012/03/14 面试题
社区工作者先进事迹
2014/01/18 职场文书
英语教师求职信
2014/06/16 职场文书
干部四风问题整改措施思想汇报
2014/10/13 职场文书
2014年计生工作总结
2014/11/21 职场文书
先进工作者申报材料
2014/12/23 职场文书
金正昆讲礼仪观后感
2015/06/11 职场文书
2016国培学习心得体会
2016/01/08 职场文书