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数据库并展示在前端页面的实现代码
May 02 MySQL
mysql5.7使用binlog 恢复数据的方法
Jun 03 MySQL
Unity连接MySQL并读取表格数据的实现代码
Jun 20 MySQL
MySQL系列之十四 MySQL的高可用实现
Jul 02 MySQL
MySQL 聚合函数排序
Jul 16 MySQL
MySQL非空约束(not null)案例讲解
Aug 23 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
浅谈MySQL表空间回收的正确姿势
Oct 05 MySQL
深入解析MySQL索引数据结构
Oct 16 MySQL
Mysql Innodb存储引擎之索引与算法
Feb 15 MySQL
mysql字段为NULL索引是否会失效实例详解
May 30 MySQL
MySQL提升大量数据查询效率的优化神器
Jul 07 MySQL
进阶篇之linux环境下安装MySQL数据库
MySQL的存储函数与存储过程的区别解析
Apr 08 #MySQL
MySQL数据库查询进阶之多表查询详解
MySQL中一条SQL查询语句是如何执行的
解决MySQL Varchar 类型尾部空格的问题
Apr 06 #MySQL
mysql的单列多值存储实例详解
Apr 05 #MySQL
详细聊一聊mysql的树形结构存储以及查询
You might like
PH P5.2至5.5、5.6的新增功能详解
2014/07/14 PHP
php读取出一个文件夹及其子文件夹下所有文件的方法示例
2017/06/15 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
在一个form用一个SUBMIT(或button)分别提交到两个处理表单页面的代码
2007/02/15 Javascript
Ajax+Json 级联菜单实现代码
2009/10/27 Javascript
一个简单的网站访问JS计数器 刷新1次加1次访问
2012/09/20 Javascript
JQuery限制复选框checkbox可选中个数的方法
2015/04/20 Javascript
jQuery插件制作之参数用法实例分析
2015/06/01 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
2015/06/03 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
JavaScript 对象详细整理总结
2016/09/29 Javascript
JS实现重新加载当前页面或者父页面的几种方法
2016/11/30 Javascript
nodejs 生成和导出 word的实例代码
2018/07/31 NodeJs
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
2019/05/05 Javascript
详解vue中使用protobuf踩坑记
2019/05/07 Javascript
Vue toFixed保留两位小数的3种方式
2020/10/23 Javascript
Python文件及目录操作实例详解
2015/06/04 Python
python开发之文件操作用法实例
2015/11/13 Python
Python排序搜索基本算法之插入排序实例分析
2017/12/11 Python
Python实现查询某个目录下修改时间最新的文件示例
2018/08/29 Python
django+echart绘制曲线图的方法示例
2018/11/26 Python
在Python运行时动态查看进程内部信息的方法
2019/02/22 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
2020/03/31 Python
python+requests接口压力测试500次,查看响应时间的实例
2020/04/30 Python
使paramiko库执行命令时在给定的时间强制退出功能的实现
2021/03/03 Python
MVMT手表官方网站:时尚又实惠的高品质手表
2016/12/04 全球购物
一套C++笔试题面试题
2012/06/06 面试题
市场营销专业推荐信
2013/11/03 职场文书
简历中自我评价范文3则
2013/12/14 职场文书
中国入世承诺
2014/04/01 职场文书
2014年班组建设工作总结
2014/12/01 职场文书
针对吵架老公保证书
2015/05/08 职场文书
2015年干部教育培训工作总结
2015/05/15 职场文书
python 使用Tensorflow训练BP神经网络实现鸢尾花分类
2021/05/12 Python