MySQL通过show status查看、explain分析优化数据库性能

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_%';

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

-- 查看全局所有统计的值

SHOW GLOBAL STATUS LIKE 'Com_%';

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;

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

  • 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;

可以发现建立索引后对goods_stock_price子表需要扫描的行数明显减少(从 3 行减少到1行),可见索引的使用可以大大提高数据库的访问速度,尤其在表很庞大的时候这种优势更为明显。

到此这篇关于MySQL通过show status查看、explain分析优化数据库性能的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • MySQL数据库优化之分表分库操作实例详解

    本文实例讲述了MySQL数据库优化之分表分库操作.分享给大家供大家参考,具体如下: 分表分库 垂直拆分 垂直拆分就是要把表按模块划分到不同数据库表中(当然原则还是不破坏第三范式),这种拆分在大型网站的演变过程中是很常见的.当一个网站还在很小的时候,只有小量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求.其实,相对于垂直切分更进一步的是服务化改造,说得简单就是要把原来强耦合的系统拆分成多个弱耦合的服务,通过服务间的

  • 简单了解MySQL数据库优化技巧

    一个成熟的数据库架构并不是一开始设计就具备高可用.高伸缩等特性的,它是随着用户量的增加,基础架构才逐渐完善.这篇文章主要谈谈MySQL数据库在发展周期中所面临的问题及优化方案,暂且抛开前端应用不说,大致分为以下五个阶段: 阶段一:数据库表设计 项目立项后,开发部门根据产品部门需求开发项目. 开发工程师在开发项目初期会对表结构设计.对于数据库来说,表结构设计很重要,如果设计不当,会直接影响到用户访问网站速度,用户体验不好!这种情况具体影响因素有很多,例如慢查询(低效的查询语句).没有适当建立索引.

  • MySQL数据库查询性能优化策略

    优化查询 使用Explain语句分析查询语句 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句. 通过对查询语句的分析,可以了解查询语句的执行情况,找出查询语句执行的瓶颈,从而优化查询语句. 使用索引查询 MySql中提高性能的一个最有效的方式就是对数据表设计合理的索引. 索引提供了高效访问数据的方法,并且加快查询速度. 如果查询时没有使用索引,那么查询语句将扫描表中所有的记录.在数据量大的时候,这样查询速度会很慢. 使用索引进行查询,查

  • mysql数据库常见的优化操作总结(经验分享)

    前言 对于一个以数据为中心的应用,数据库的好坏直接影响到程序的性能,因此数据库性能至关重要.所以mysql数据库的优化操作大家都要有所了解,本文就主要总结了mysql数据库中常见的优化操作,下面话不多说了,来看看详细的介绍吧. 一.Index索引 将Index放第一位,不用说,这种优化方式我们一直都在悄悄使用,那便是主键索引.有时候我们可能并不在意,如果定义适合的索引,数据库查询性能(速度)将提高几倍甚至几十倍. 普通索引 作用是提高查询速度. 建表,创建索引 CREATE TABLE tbl_

  • 简单了解MYSQL数据库优化阶段

    引言 大家在面试的时候,是否遭遇过,面试官询问 你们是如何进行数据库优化的? 那这个问题应该怎么答呢?其实写这个题材的原因是我这几天看到各公众号转的一篇数据库调优的知识(不上链接了),我就稍微翻了几下,上面动不动就来说要对数据库进行水平拆分,我就想反问各位读者,你们几个人经历过水平拆分?现在很多文章,实践性实在太差,只能说纯理论分析. 这篇文章最早来自知乎的一个提问,我在其基础上完善了一下. 第一阶段 优化sql和索引 这才是调优的第一阶段啊,为什么呢? 因为这一步成本最低啊,不需要加什么中间件

  • MySQL数据库优化之索引实现原理与用法分析

    本文实例讲述了MySQL数据库优化之索引实现原理与用法.分享给大家供大家参考,具体如下: 索引 什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的记录数量越多,这个操作的代价就越高.如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置.如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍.

  • 9种 MySQL数据库优化的技巧

    目录 1.选择最合适的字段属性 2.尽量把字段设置为NOT NULL 3.使用连接(JOIN)来代替子查询(Sub-Queries) 4.使用联合(UNION)来代替手动创建的临时表 5.事务 6.使用外键 7.锁定表 8.使用索引 9.优化de的查询语句 9.1 不使用子查询 9.2 避免函数索引 9.3 用IN来替换OR 9.4 LIKE双百分号无法使用到索引 9.5 读取适当的记录LIMIT M,N 9.6 避免数据类型不一致 9.7 分组统计可以禁止排序 9.8 避免随机取记录 9.9

  • MYSQL数据库表结构优化方法详解

    本文实例讲述了MYSQL数据库表结构优化方法.分享给大家供大家参考,具体如下: 选择合适的数据类型 1.使用可以存下你的数据的最小的数据类型 2.使用简单的数据类型.Int要比varchar类型在mysql处理上简单 3.尽可能的使用not null定义字段 4.尽量少用text类型,非用不可时最好考虑分表 使用int来存储日期时间,利用FROM_UNIXTIME()[将int类型时间戳转换成日期时间格式],UNIX_TIMESTAMP()[将日期时间格式转换成int类型]两个函数进行转换 使用

  • 详解MySQL数据库优化的八种方式(经典必看)

    引言: 关于数据库优化,网上有不少资料和方法,但是不少质量参差不齐,有些总结的不够到位,内容冗杂. 偶尔发现了这篇文章,总结得很经典,文章流量也很大,所以拿到自己的总结文集中,积累优质文章,提升个人能力,希望对大家今后开发中也有帮助 1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小. 例如,在定义邮政编码这个字段时,如果将其设置为CHAR(

  • MySQL数据库性能优化介绍

    目录 为什么做优化?? 从哪些方面入手?? 解决方案是什么???  要怎样选择??? SQL优化 总结 为什么做优化?? 因为数据量太多了,项目部署上线再到用户使用,每天数据增长几十万条,给服务器带来非常大的负担,互联网一直追求高性能,可是随着业务规模变大,用户数量变多,服务器的性能越来越差,因此我们不得不对数据库有更高要求. 从哪些方面入手?? 第一,是查询的速度,我们期望数据量到达TB级别仍然能够实现百万级别查询速度. 第二.是并发量,我们对它的要求能够同时处理几千甚至上万的并发访问,还要配

  • Mysql数据库中数据表的优化、外键与三范式用法实例分析

    本文实例讲述了Mysql数据库中数据表的优化.外键与三范式用法.分享给大家供大家参考,具体如下: 数据表优化 将商品信息表进行优化 1.创建商品种类表: create table if not exists goods_cates( id int unsigned primary key auto_increment, name varchar(40) not null ); 2.将商品种类写入商品种类表中: 注意:插入另一个表的查询结果不需要加values insert into goods_

  • MySQL数据库优化的六种方式总结

    目录 方法一 方法二 方法五 方法六 附:mysql优化的常用方法 总结 方法一 使用连接来代替子查询(Sub-Queries).可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中. DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT customerid FROM salesinfo) 方法二 事务.不是所有的数据库操作都可以只用一条或少数几条SQL语句就可以完成的.更多的时候是需要用到一系

随机推荐