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:扫描行的数量。
●Extra:执行情况的说明和描述。

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

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

CREATE INDEX idx_stock_price_1 ON goods_stock_price (GoodsStockID);

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

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大全

(2)MySQL进阶篇SQL优化(show status、explain分析)的更多相关文章

  1. (6)MySQL进阶篇SQL优化(MyISAM表锁)

    1.MySQL锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源 (如 CPU.RAM.I/O 等)的抢占以外,数据也是一种供许多用户共享的资源.如何保证数 据并 ...

  2. (4)MySQL进阶篇SQL优化(常用SQL的优化)

    1.概述 前面我们介绍了MySQL中怎么样通过索引来优化查询.日常开发中,除了使用查询外,我们还会使用一些其他的常用SQL,比如 INSERT.GROUP BY等.对于这些SQL语句,我们该怎么样进行 ...

  3. (3)MySQL进阶篇SQL优化(索引)

    1.索引问题 索引是数据库优化中最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数 的SQL性能问题.本章节将对MySQL中的索引的分类.存储.使用方法做详细的介绍. 2.索引的存储分类 ...

  4. (11)MySQL进阶篇SQL优化(InnoDB锁问题排查与解决)

    1.概述 前面章节之所以介绍那么多锁的知识点和示例,其实最终目的就是为了排查与解决死锁的问题,下面我们把之前学过锁知识重温与补充一遍,然后再通过例子演示下如果排查与解决死锁. 2.前期准备 ●数据库事 ...

  5. (5)MySQL进阶篇SQL优化(优化数据库对象)

    1.概述 在数据库设计过程中,用户可能会经常遇到这种问题:是否应该把所有表都按照第三范式来设计?表里面的字段到底改设置为多大长度合适?这些问题虽然很小,但是如果设计不当则可能会给将来的应用带来很多的性 ...

  6. (7)MySQL进阶篇SQL优化(InnoDB锁-事务隔离级别 )

    1.概述 在我们在学习InnoDB锁知识点之前,我觉得有必要让大家了解它的背景知识,因为这样才能让我们更系统地学习好它.InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION ...

  7. (8)MySQL进阶篇SQL优化(InnoDB锁-共享锁、排他锁与意向锁)

    1.锁的分类 锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制.之前MyISAM锁章节已经讲过锁分类,而InnoDB锁按照粒度分为锁定整个表的表级锁(table-level l ...

  8. (9)MySQL进阶篇SQL优化(InnoDB锁-记录锁)

    1.概述 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点意味着:只有通过索引条件检索 ...

  9. (10)MySQL进阶篇SQL优化(InnoDB锁-间隙锁)

    1.概述 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做"间隙(GAP)&quo ...

随机推荐

  1. golang1.16新特性速览

    今天是假期最后一天,明天起大家也要陆续复工了.golang1.16也在今天正式发布了. 原定计划是2月1号年前发布的,不过迟到也是golang的老传统了,正好也趁着最后的假期快速预览一下golang1 ...

  2. Web API 设计

    Web API 设计 The Design of Web APIs free online ebook https://www.manning.com/books/the-design-of-web- ...

  3. ESLint & jsx-quotes & quotes

    ESLint & jsx-quotes & quotes bug { "jsx-quotes": [ "error", "prefer ...

  4. MacBook Pro 2019 13 inch & screen blink

    MacBook Pro 2019 13 inch & screen blink MacBook Pro 闪屏 https://macreports.com/mac-how-to-trouble ...

  5. 2021-2-19:请问你知道 Java 如何高性能操作文件么?

    一般高性能的涉及到存储框架,例如 RocketMQ,Kafka 这种消息队列,存储日志的时候,都是通过 Java File MMAP 实现的,那么什么是 Java File MMAP 呢? 什么是 J ...

  6. SSL/TLS协议详解(下)——TLS握手协议

    本文转载自SSL/TLS协议详解(下)--TLS握手协议 导语 在博客系列的第2部分中,对证书颁发机构进行了深入的讨论.在这篇文章中,将会探索整个SSL/TLS握手过程,在此之前,先简述下最后这块内容 ...

  7. Tango with django 1.9 中文——2.准备工作

    在正式开始写代码之前,设置好开发环境是非常重要的.你要确保所有必须的组件都已安装好.本章将概述五个你需要了解的关键组件的设置和使用.清单如下: 使用命令行 Python Python包管理器pip和虚 ...

  8. .NET Core中的Worker Service

    当你想到ASP.NET Core时,可能会想到Web应用程序后端代码,包括MVC和WebAPI.MVC视图和Razor页面还允许使用后端代码生成带有HTML元素的前端UI.全新的Blazor更进一步, ...

  9. Latency 和 Delay 区别

    时延:Latency 指的是一个报文进入一台设备以致这台设备所经历的时间.实际上考验的是报文在这台设备上消耗的时间.时间越短,这台设备的性能越高.   延时:Delay 是指一个操作和另个一个操作之间 ...

  10. 一个 java 文件的执行过程详解

    平时我们都使用 idea.eclipse 等软件来编写代码,在编写完之后直接点击运行就可以启动程序了,那么这个过程是怎么样的? 总体过程 我们编写的 java 文件在由编译器编译后会生成对应的 cla ...