如何确认服务器是否达到了性能最佳状态?
为什么某条语句的执行不够快?
如何诊断被用户描述成“停顿”、“堆积”或者“卡死”的某些间歇性疑难故障?
1. 性能优化简介
每个人关于性能的定义都不大相同,我们在这里给性能一个正式的定义。完成某件任务所需要的时间度量,即性能就是就是响应时间。如果把性能优化仅仅看成是提升每秒查询量,其实是吞吐量优化。吞吐量的提升可以看作为性能优化的副产品。如果我们的目标是降低响应时间,那么就需要理解为什么服务器执行查询需要那么多是的时间,然后去减少或者消除哪些对获得查询结果来说不必要的工作。
总体来说,思路应该是,先找哪里慢、看为什么慢;然后再针对性的去进行调优,而不是上来就调整一些参数
在进行查找的时候要避免选择错误的测量范围,比如一个常见的错误就是,先看慢查询,然后又去排查整个服务器的情况来判断问题在哪里。如果确认有慢查询,那么就应该测量慢查询,而不是测量整个服务器。测量的应该是从慢查询的开始到结束的时间,而不是查询之前或查询之后的时间。
完成一项任务所需要的时间可以分成两部分:执行时间和等待时间。
优化任务执行时间,最好的办法是通过测量定位不同的子任务花费的时间,然后优化掉一些子任务、降低子任务的执行频率或者提升子任务的执行效率。
优化任务等待时间,等待有可能是由其他系统间影响导致,任务之间也可能由于争用磁盘或者CPU资源而相互影响。
1.1 通过性能剖析进行优化
性能剖析是测量和分析时间花费在哪里的主要方法。性能剖析一般有两个步骤:
- 测量任务所花费的时间;
- 然后对结果进行统计和排序,将重要的任务排到前面;
我们将讨论两种类型的性能剖析,基于执行时间的分析和基于等待的分析。基于执行时间的分析是研究是什么任务的执行时间最长,而基于等待的分析则是判断任务在什么地方被阻塞的时间最长。
1.2 理解性能剖析
值得优化的查询(worthwhile query)
- 一些只占总相应时间比重很小的查询是不值得优化的
- 如果优化的成本大于收益,就应当停止优化
异常情况
如果没有在性能分析上出现,但某些任务执行次数很少,但每次执行都非常慢。但因为执行效率频率低,所以在总相应时间上并不突出。未知的未知
一款好的性能剖析工具会显示可能的“丢失的时间”。丢失的时间指的是任务的总时间和实际的测量到的时间之间的差。被隐藏的细节
只相信平均值是不可靠的,可以通过直方图、百分比、标准差、偏差指数等多维度进行查看。2. 对应用程序进行性能剖析
对系统进行的性能剖析建议是自上而下地进行,这样可以追踪自用户发起到服务器响应的整个流程。性能瓶颈有可能有很多影响因素:
- 外部资源,比如调用了外部的 Web 服务或搜索引擎。
- 应用需要处理大量的数据,比如分析一个超大的 XML 文件。
- 在循环中执行昂贵的操作,比如滥用正则表达式。
- 使用了低效的算法,比如使用暴力搜索算法(naive search algorithm)来查找列表中的项。
书中建议使用 New Relic 的软件服务产品。因为书本出版较早,所以作者只推荐了一个。这里关于此项就不做过多阐述。关于优化可查看 传送门 -> JavaWeb优化
3. 剖析 MySQL 查询
3.1 剖析服务器负载
开启慢查询日志
如果长期开启慢查询日志,注意要部署日志轮转工具。或者不要长期启用慢查询日志,只在需要收集负载样本的期间开启即可。
抓取 TCP 网络包
通过抓取 TCP 网络包, 然后根据MySQL的客户端/服务端协议进行解析。可以通过 tcpdump 将数据包保存下来,然后使用 pt-query-digest
的--type=tcpdump
选项来解析并分析查询。
3.2 分析查询日志
可以选择一些典型的时间窗口如业务高峰期的一个小时内,利用慢查询日志捕获服务器上的所有查询,并进行分析。可以通过慢查询日志记录查询或者使用 pt-query-digest 分析 tcpdump 的结果。
4. 总结
解决性能问题的方法首先是要找到问题,然后选择合适的技术来解答这些问题。如果想提升服务器的总体性能,那么最好是将所有查询记录到日志中,然后利用 pt-query-digest 工具生成系统级别的剖析报告。如果是要追查某些性能低下的查询,可以使用 SHOW PROFILE 或者 EXPLAIN 方法。
如果找不到查询性能低下的原因,那有可能是服务器级别的性能问题。这样就可以结合绘制服务器状态的数据进行分析。