第三章 服务器性能剖析

3.1性能优化简介

毎个人在不同场景下对性能有不同的
理解,但本章将给性能一个正式的定义。我们将性能定义为完成某件任务所需要的时间
度量,换句话说,性能即响应时间,这是一个非常重要的原则。我 们通过任务和时间而
不是资源来测量性能。数据库服务器的目的是执行SQL语句,所以它关注的任务是査询
或者语句,如SELECT. UPDATE. DELETE等.数据库服务器的性能用査询的响应时间来度量,单位是每个花费的时间.

什么是优化?

很多人对此很迷茫。假如你认为性能优化是降低CPU利用率,那么可以减少对资源的使 用。
但这是一个陷阱,资源是用来消耗并用来工作的,所以有时候消耗更多的资源能够 加快査询速度。很多时候将使用老版本InnoDB引擎的MySQL升级到新版本后,CPU 利用率会上升得很厉害,这并不代表性能出现了问题,反而说明新版本的InnoDB对资 源的利用率上升了。査询的响应时间则更能体现升级后的性能是不是变得更好。版本升 级有时候会带来一些bug,比如不能利用某些索引从而导致CPU利用率上升。CPU利用率只是一种现象,而不是很好的可度量的目标。
同样,如果把性能优化仅仅看成是提升每秒査询量,这其实只是吞吐量优化。吞吐量的 提升可以看作性能优化的副产品注3。对査询的优化可以让服务器每秒执行更多的査询, 因为每条査询执行的时间更短了(吞吐量的定义是单位时间内的査询数量,这正好是我 们对性能的定义的倒数)。

所以如果目标是降低响应时间,那么就需要理解为什么服务器执行査询需要这么多时间, 然后去减少或者消除那些对获得査询结果来说不必要的工作。也就是说,先要搞清楚时 间花在哪里。这就引申出优化的第二个原则:无法测量就无法有效地优化。所以第一步 应该测量时间花在什么地方。
我们观察到,很多人在优化时,都将精力放在修改一些东西上,却很少去进行精确的测量。 我们的做法完全相反,将花费非常多,甚至90%的时间来测量响应时间花在哪里。如果 通过测量没有找到答案,那要么是测量的方式错了,要么是测量得不够完整。如果测量 了系统中完整而且正确的数据,性能问题一般都能暴露出来,对症下药的解决方案也就 比较明了。测量是一项很有挑战性的工作,并且分析结果也同样有挑战性,测出时间花 在哪里,和知道为什么花在那里,是两码事

完成一项任务所需要的时间可以分成两部分:执行时间和等待时间
如果要优化任务的 执行时间,最好的办法是通过测量定位不同的子任务花费的时间,然后优化去掉一些子 任务、降低子任务的执行频率或者提升子任务的效率。
而优化任务的等待时间则相对要 复杂一些,因为等待有可能是由其他系统间接影响导致,任务之间也可能由于争用磁盘 或者CPU资源而相互影响。根据时间是花在执行还是等待上的不同,诊断也需要不同的 工具和技术。

3.1.1通过性能剖析进行优化

性能剖析是测量和分析时间花费在哪里的主要方法。性能剖析一般有两个步骤:1.测量任务所花费的时间;2.对结果进行统计和排序,将重要的任务排到前面。
性能剖析工具的工作方式基本相同。在任务开始时启动计时器,在任务结束时停止计时器,然后用结束时间减去启动时间得到响应时间。也有些工具会记录任务的父任务。这 些结果数据可以用来绘制调用关系图,但对于我们的目标来说更重要的是,可以将相似 的任务分组并进行汇总。对相似的任务分组并进行汇总可以帮助对那些分到一组的任务 做更复杂的统计分析,但至少需要知道每一组有多少任务,并计算出总的响应时间。通 过性能剖析报告(profile report)可以获得需要的结果。性能剖析报告会列出所有任务列 表。每行记录一个任务,包括任务名、任务的执行时间、任务的消耗时间、任务的平均 执行时间,以及该任务执行时间占全部时间的百分比。性能剖析报告会按照任务的消耗时间进行降序排序。

我们将实际地讨论两种类型的性能剖析:基于执行时间的分析和基于等待的分析。基于 执行时间的分析研究的是什么任务的执行时间最长,而基于等待的分析则是判断任务在什么地方被阻塞的时间最长。

举个例子,在Percona Server 5.0中,慢査询日志揭露了一些性能低下的原因,如磁盘I/O 等待或者行级锁等待。如果日志中显示一条査询花费10秒,其中9.6秒在等待磁盘I/O, 那么追究其他4%的时间花费在哪里就没有意义,磁盘I/O才是最重要的原因。

3.1.2理解性能剖析

MySQL的性能剖析(profile)将最重要的任务展示在前面,但有时候没显示出来的信息也很重要。可以参考一下前面提到过的性能剖析的例子。不幸的是,尽管性能剖析输出 了排名、总计和平均值,但还是有很多需要的信息是缺失的。

值得优化的查询(worthwhile query)

性能剖析不会自动给出哪些査询值得花时间去优化。这把我们带回到优化的本意, 如果你读过Cary Millsap的书,对此就会有更多的理解。这里我们要再次强调两点: 第一,一些只占总响应时间比重很小的査询是不值得优化的。
根据阿姆达尔定律 (Amdahl5s Law),对一个占总响应时间不超过5%的査询进行优化,无论如何努力, 收益也不会超过5%。
第二,如果花费了 1000美元去优化一个任务,但业务的收入 没有任何增加,那么可以说反而导致业务被逆优化了 1 000美元。如果优化的成本大于收益,就应当停止优化

异常情况

某些任务即使没有出现在性能剖析输出的前面也需要优化。比如某些任务执行次数很少,但每次执行都非常慢,严重影响用户体验。因为其执行频率低,所以一款好的性能剖析工具会显示可能的“丢失的时间”。丢失的时间指的是任务的总时间和实际测量到的时间之间的差。例如,如果处理器的CPU时间是10秒,而剖析 到的任务总时间是9.7秒,那么就有300毫秒的丢失时间。这可能是有些任务没有 测量到,也可能是由芋测量的误差和精度问题的缘故。如果工具发现了这类问题, 要引起重视,因为有可能错过了某些重要的事情。即使性能剖析没有发现丢失时间,也需要注意考虑这类问题存在的可能性,这样才不会错过重要的信息。

被掩藏的细节

性能剖析无法显示所有响应时间的分布。只相信平均值是非常危险的,它会隐藏很 多信息,而且无法表达全部情况。Peter经常举例说医院所有病人的平均体温没有任 何价值注6。假如在前面的性能剖析的例子的第一项中,如果有两次査询的响应时间是 1秒,而另外12 771次査询的响应时间是几十微秒,结果会怎样?只从平均值里是 无法发现两次1秒的査询的。要做出最好的决策,需要为性能剖析里输出的这一行 中包含的12 773次査询提供更多的信息,尤其是更多响应时间的信息,比如直方图、 , 百分比、标准差、偏差指数等。
好的工具可以自动地获得这些信息。实际上,pt-query-digest就在剖析的结果里包含了 很多这类细节信息,并且输出在剖析报告中。对此我们做了简化,可以将精力集中在重 要而基础的例子上:通过排序将最昂贵的任务排在前面。本章后面会展示更多丰富而有 用的性能剖析的例子。
在前面的性能剖析的例子中,还有一个重要的缺失,就是无法在更高层次的堆栈中进行 交互式的分析。当我们仅仅着眼于服务器中的单个査询时,无法将相关査询联系起来, 也无法理解这些査询是否是同一个用户交互的一部分。性能剖析只能管中窥豹,而无法 将剖析从任务扩展至事务或者页面査看(page view)的级别。

3.2对应用程序进行性能剖析

剖析应 用程序一般比剖析数据库服务器容易,而且回报更多。虽然前面的演示例子都是针对MySQL服务器的剖析,但对系统进行性能剖析还是建议自上而下地进行,这样可以追 踪自用户发起到服务器响应的整个流程。虽然性能问题大多数情况下都和数据库有关,但应用导致的性能问题也不少。性能瓶颈可能有很多影响因素:

  • 外部资源,比如调用了外部的Web服务或者搜索引擎。
  • 应用需要处理大量的数据,比如分析一个超大的XML文件。
  • 在循环中执行昂贵的操作,比如滥用正则表达式。
  • 使用了低效的算法,比如使用暴力搜索算法(naive search algorithm)来査找列表中 的项。
性能剖析本身会导致服务器变慢吗?
说“是的”,是因为性能剖析确实会导致应用慢一点;说“不是”,是因为性能剖析 可以帮助应用运行得更快。先别急,下面就解释一下为什么这么说。
性能剖析和定期检测都会带来额外开销。问题在于这部分的开销有多少,并且由此 获得的收益是否能够抵消这些开销。
大多数设计和构建过高性能应用程序的人相信,应该尽可能地测量一切可以测量的 地方,并且接受这些测量带来的额外开销,这些开销应该被当成应用程序的一部分。 Oracle的性能优化大师Tom Kyte曾被问到Oracle中的测量点的开销,他的回答是, 测量点至少为性能优化贡献了 10%。对此我们深表赞同,而且大多数应用并不需 要每天都运行详细的性能测量,所以实际贡献甚至要超过10%。即使不同意这个 观点,为应用构建一些可以永久使用的轻量级的性能剖析也是有意义的。如果系统 没有每天变化的性能统计,则碰到无法提前预知的性能瓶颈就是一件头痛的事情。 发现问题的时候,如果有历史数据,则这些历史数据价值是无限的。而且性能数据 还可以帮助规划好硬件采购、资源分配,以及预测周期性的性能尖峰。
那么何谓“轻量级”的性能剖析?比如可以为所有SQL语句计时,加上脚本总时 间统计,这样做的代价不高,而且不需要在每次页面查看(page view)时都执行。 如果流量趋势比较稳定,随机采样也可以,随机采样可以通过在应用程序中设置实 现:
<?php 
  $profilling_enabled=rand(0,100)>99
?>
这样只有1%的会话会执行性能采样,来帮助定位一些严重的问题。这种策略在生 产环境中尤其有用,可以发现一些其他方法无法发现的问题。

3.2.1测量PHP应用程序 (咱不看了 有兴趣可以自己查阅)
3.3剖析MySQL查询

对査询进行性能剖析有两种方式,每种方式都有各自的问题,本章会详细介绍。

  • 可以剖析整个数据库服务器,这样可以分析出哪些査询是主要的压力来源(如果已经在最上面 的应用层做过剖析,则可能已经知道哪些査询需要特别留意)。
  • 定位到具体需要优化的査询后,也可以钻取下去对这些査询进行单独的剖析,分析哪些子任务是响应时间的主要消耗者。
3.3.1剖析服务器负载

服务器端的剖析很有价值,因为在服务器端可以有效地审计效率低下的査询。定位和优化“坏”查询能够显著地提升应用的性能,也能解决某些特定的难题。还可以降低服务 器的整体压力,这样所有的査询都将因为减少了对共享资源的争用而受益(“间接的好 处”)。降低服务器的负载也可以推迟或者避免升级更昂贵硬件的需求,还可以发现和定 位糟糕的用户体验,比如某些极端情况。
MySQL的每一个新版本中都增加了更多的可测量点。如果当前的趋势可靠的话,那么在性能方面比较重要的测量需求很快能够在全球范围内得到支持。但如果只是需要剖析 并找出代价高的査询,就不需要如此复杂。有一个工具很早之前就能帮到我们了,这就是慢査询日志。

捕获MySQL的查询到日志文件中
在MySQL中,慢查询日志最初只是捕获比较“慢”的査询,而性能剖析却需要针对所 有的查询。而且在MySQL 5.0及之前的版本中,慢査询日志的响应时间的单位是,粒 度太粗了。幸运的是,这些限制都已经成为历史了。在MySQL 5.1及更新的版本中,慢 日志的功能已经被加强,可以通过设置long_query_time为0来捕获所有的査询,而且<3D 査询的响应时间单位已经可以做到微秒级。如果使用的是Percona Server,那么5.0版本 就具备了这些特性,而且Percona Server提供了对日志内容和査询捕获的更多控制能力。
在MySQL的当前版本中,慢査询日志是开销最低、精度最高的测量査询时间的工具。 如果还在担心开启慢査询日志会带来额外的I/O开销,那大可以放心。我们在I/O密集 型场景做过基准测试,慢查询日志带来的开销可以忽略不计(实际上在CPU密集型场景 的影响还稍微大一些)。更需要担心的是日志可能消耗大量的磁盘空间。如果长期开启 慢査询日志,注意要部署日志轮转(log rotation)工具。或者不要长期启用慢査询日志, 只在需要收集负载样本的期间开启即可。

MySQL还有另外一种査询日志,被称之为“通用日志”,但很少用于分析和剖析服务器 性能。通用日志在査询请求到服务器时进行记录,所以不包含响应时间和执行计划等重要信息。MySQL 5.1之后支持将日志记录到数据库的表中,但多数情况下这样做没什么必要。这不但对性能有较大影响,而且MySQL 5.1在将慢査询记录到文件中时已经支持 微秒级别的信息,然而将慢査询记录到表中会导致时间粒度退化为只能到秒级。而秒级别的慢査询日志没有太大的意义。

Percona Server的慢査询日志比MySQL官方版本记录了更多细节且有价值的信息,如 査询执行计划、锁、I/O活动等。这些特性都是随着处理各种不同的优化场景的需求而 慢慢加进来的。另外在可管理性上也进行了增强。比如全局修改针对每个连接的 query_time的阈值,这样当应用使用连接池或者持久连接的时候,可以不用重置会话级 别的变量而启动或者停止连接的査询日志。总的来说,慢査询日志是一种轻量而且功能 全面的性能剖析工具,是优化服务器査询的利器。

有时因为某些原因如权限不足等,无法在服务器上记录査询。这样的限制我们也常常碰 到,所以我们开发了两种替代的技术,都集成到了 Percona Toolkit中的pt-query-digest中。 第一种是通过-processlist选项不断査看SHOW FULL PROCESSLIST的输出,记录査询第 一次出现的时间和消失的时间。某些情况下这样的精度也足够发现问题,但却无法捕 获所有的査询。一些执行较快的査询可能在两次执行的间隙就执行完成了,从而无法捕获到。

第二种技术是通过抓取TCP网络包,然后根据MySQL的客户端/服务端通信协议进 行解析。可以先通过tcpdump将网络包数据保存到磁盘,然后使用pt-query-digest的 —type^tcpdump选项来解析并分析査询。此方法的精度比较高,并且可以捕获所有査询。还可以解析更高级的协议特性,比如可以解析二进制协议,从而创建并执行服务端预解析的语句(prepared statement)及压缩协议。另外还有一种方法,就是通过MySQL Proxy代理层的脚本来记录所有査询,但在实践中我们很少这样做

分析查询日志
强烈建议大家从现在起就利用慢査询日志捕获服务器上的所有査询,并且进行分析。可 以在一些典型的时间窗口如业务高峰期的一个小时内记录査询。如果业务趋势比较均衡, 那么一分钟甚至更短的时间内捕获需要优化的低效查询也是可行的。
不要直接打开整个慢査询日志进行分析,这样做只会浪费时间和金钱。首先应该生成一 个剖析报告,如果需要,则可以再査看日志中需要特别关注的部分。自顶向下是比较好 的方式,否则有可能像前面提到的,反而导致业务的逆优化。
从慢査询日志中生成剖析报告需要有一款好工具,这里我们建议使用pt-query-digest, 这毫无疑问是分析MySQL査询日志最有力的工具。该工具功能强大,包括可以将査询
报告保存到数据库中,以及追踪工作负载随时间的变化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值