如何确认服务器是否达到了性能最佳状态?
为什么某条语句的执行不够快?
如何诊断被用户描述成“停顿”、“堆积”或者“卡死”的某些间歇性疑难故障?

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 方法。
如果找不到查询性能低下的原因,那有可能是服务器级别的性能问题。这样就可以结合绘制服务器状态的数据进行分析。