第三章 服务器性能剖析
无法测量就无法优化。所以第一步应该测量时间花在什么地方
有两种比较常见的情况会导致不合适的测量:
- 在错误的时间启动和停止测量
- 测量的是聚合后的信息,而不是目标活动本身
3.1.1 通过性能剖析进行优化
性能剖析是测量和分析时间花费在哪里的主要方法。性能剖析一般有两个步骤:测量任务所花费的时间;然后对结果进行统计和排序,将重要的任务排到前面。
- 基于执行时间的分析
- 基于等待的分析
3.1.2 理解性能剖析
尽管性能剖析输出了排名、总计和平均值,但还是有很多需要的信息是缺失的:
- 值得优化的查询
- 一些只占总响应时间比重很小的查询是不值得优化的。根据阿姆达定律,对一个占总响应时间不超过5%的查询进行优化,无论如何努力收益也不会超过5%.
- 如果优化的成本大于收益,就应当停止优化
- 异常情况
- 某些任务即使没有出现在性能剖析输出的前面也需要优化
- 未知的未知
- 一款好的性能剖析工具会显示可能的“丢失的时间“。
- 被隐藏的细节
- 性能剖析无法显示所有响应时间的分布。
3.2 对应用程序进行性能剖析
性能瓶颈可能有很多影响因素:
- 外部资源,比如:调用了外部的web服务或者搜索引擎
- 应用需要处理大量的数据,比如:分析一个超大的XML文件
- 在循环中执行昂贵的操作,比如:滥用正则表达式
- 使用了低效率的算法,比如:使用暴力搜索算法(native search algorithm)来查找列表中的项
3.3 剖析MySQL查询
3.3.1 剖析服务器负载
- 捕获MySQL的查询到日志文件中
- 分析查询日志
3.3.2 剖析单条查询
- 使用PROFILS命令
mysql>set profiling = 1;
mysql>select * from user;
mysql>SHOW PROFILE FOR QUERY 9;
- 使用INFOMATION_SCHEMA
select
state ,
sum(duration) as total_R,
ROUND( 100 * sum(duration) / (select SUM(duration) from information_schema.PROFILING p where query_id = 55), 2) as Pct_R,
count(*) as Calls,
SUM(duration) / count(*) as "R/Call"
from
information_schema.PROFILING
where
QUERY_ID = 55
GROUP by
STATE
order by
total_R desc;
- 使用 SHOW STATUS : 返回了一些计数器
- 使用慢查询日志
- 使用Performmance Schema
3.3.3 使用性能剖析
3.4 诊断间歇性问题
已经解决的实际案例:
- 应用通过curl从一个运行得很慢的外部服务来获取汇率报价的数据
- memcached缓存中的一些重要条目过期,导致大量请求落到MySQL
- DNS偶尔会有超时现象
- 可能是由于互斥锁争用,或者内部删除查询缓存的算法效率太低的缘故,MySQL查询有时候会导致服务有短暂的停顿
- 当并发度超过某个阀值
3.4.1 单条查询问题还是服务器问题
- 使用SHOW GLOBAL STATUS
- 使用SHOW PROCESSLIST
- 使用查询日志
- 理解发现的问题
- 可视化的数据最具有说服力
3.4.2 捕获诊断数据
- 诊断触发器
- 需要收集什么样的数据
- 解释数据结果
3.4.3 一个诊断案例
- 收集系统数据
- 结合应用分析数据
- 发现问题或者这没有发现问题
- 发现的问题 是问题导致的结果?还是问题产生的原因?
- 到底是什么原因导致的?
- 大胆怀疑,小心求证
- 问题解决
- 复盘整个流程
究竟是什么导致了性能地下?
当一个资源变得效率低下时,应该了解一下为什么会这样。有如下可能的原因:
-
- 资源被过度使用,余量已经不足以正常工作
-
- 资源没有被正确的配置
-
- 资源已经损坏或者失灵
3.5 其他剖析工具
3.5.1 使用USER_STATISTICS表
show tables from information_schema like '%STATISTICS'
5.7版本的数据库并没有找对应的结果,查询这个SCHEMA之后,只剩下一张表information_schema.STATISTICS
3.5.2 使用strace
$ strace -cfp $(pidof mysqld)
不知道为什么,这句命令在mysql5.7并没有运行成功