什么是性能调优呢?一般是当用户抱怨“太慢了”、“性能不足”、“软硬件需要升级了”等问题时,提供较佳的性能。但不是要解决用户所说的“这系统毁了”、“它不会工作了”等问题,这可能需要的是备援回滚、提高系统可获得性(HA high Availability)等解决方案。但就数据库系统而言,规划高可获得性的架构(如SQL Cluster、Mirroring、Log Shipping、Replication等)不会提升系统性能,还要注意是否降低了性能。
而一般观测性能问题的现象有:
系统响应速度太慢。
每秒所完成的系统输出/入低于预期。
相同的环境,但每秒钟所完成的批操作较先前少。
系统资源(如CPU、内存、硬盘或网络等)长时间处于耗尽的状态。
通常调校的目标是以用户的期望为依据,除非你的数学与信息基本功非常扎实,否则很难知道调校的极限在哪。因此,我们的目标往往是符合用户的期盼即可
建立性能的基线
调校性能的第一个工作应该是建立性能的基线(baseline),所需的类型有:
昔日系统正常运行时的数据。
调校前系统的各种数据。
用户希望达到的目标。
基线是用来比较的,任何性能调校的动作都应该依凭数据,不要诉诸情绪。笔者常听到工程师说“今天的性能感觉比较差了”或是“现在系统响应比较慢了”。这种话是我们要帮用户解决问题的起因,但不应该是工程师讲的话。人的感觉非常不准,可能是心情不好,可能是对工作不满意,对系统的包容力就比较差,感觉就不好了。
系统响应比较慢,要知道正常是多少、慢了多少、时间差是多少、数据量多少、多少人同时上线、处理量多少等。也就是要有基线,有客观的数据,这才有好的调校基础。而通常笔者碰到的是:工程师与用户们忙了一天,精疲力竭后,会安慰自己“性能比较好了”。
如前文所述,一般要将用户的期待量化,例如,用户可以接受系统的响应时间是3~5 秒。而用户的期待通常是来自于以下方面。
工作需求:如一定要在某个时间点前完成,一秒之内要完成多少交易量才能满足多人访问等。
以往系统的使用经验。
一些性能数据值(benchmark):不管是厂家提供的,还是业界提出的标准值。
其他用户使用类似功能的经验。
为什么讨论这个呢?因为期待要合理。不要第一次开车开奔驰,然后误以为全世界的汽车开起来都要像这样。或许你会觉得这不可能发生。但事实上,若以往的系统是以Windows Form为基础,现在一模一样的功能,但改为以Web Form为基础,在相同的硬件上,可能响应就比较慢。毕竟以往从SQL Server或COM+/MTS直接传数据给编译过的VB 前端程序呈现结果,系统架构简单有效率且交互功能丰富。而Web版的ASP/ASP. NET应用程序要先将SQL Server或COM+/MTS的结果数据转换成HTML,再用效率也不高的HTTP通信协议返回到前端,最后还要浏览器遵从HTML 或DHTML 指示符,当前绘制界面,整体系统的性能当然不如以往的程序架构。
若用户端的机器本身很快,使用者或许还感受不到这个差异,然而笔者曾碰到的情况:使用古老的机器,但要求Web Form 长得和Win Form 一样,并且功能还要更多,而能忍受的响应时间相同,这就难如登天了。
另外,性能调校代表着成本(cost)支出,成本可能是实质的钱,也可能是工程师的时间与精力,用户的忍耐等待。在理想状况下,是把系统中最贵的部分发挥到极限,能够以最低的成本发挥系统最大的性能。若是自己开发的程序,这往往代表着硬件采购是系统开发中最贵的部分,因此,会采取重新设计系统的解决方式,如数据库逻辑使用方式重新切割、查询方式大量重载、以消耗内存的方式减少对硬盘的访问等。你可能要花掉数个工程师个把月的时间,才得以将架构重新规划,程序全面重载,或许花费如此的人力成本还不如直接更新设备,但性能调校的总体成本(total cost)并不容易计算。
笔者遇到的大部分状况是管理者会挑眼前最节约成本的事情先做。一般来说,就是要工程师着手调架构,可能是数据库的设计,也可能是程序代码重载,忙了个把月后声明失败,最后还是花钱买机器。这种仅看当前最低成本的做法有几个弊端:
用户苦等一两个月,最后还是换机器,他们会觉得工程师能力不足。
实际上浪费了人力成本。
一阵子后,性能问题又再度浮现。
在动手调校前应该对整个系统的各个瓶颈点了然于胸,各花多少成本可以解决,而该瓶颈调整后,整体系统性能可以提升多少。以笔者曾调校的系统为例,整体设计是用IE呈现IIS执行ASP的结果,ASP 调用COM+,COM+访问SQL Server。系统刚上线时,总响应时间是7秒钟,但用户可以接受的时间是3 秒钟。程序中,个别的时间消耗是IE花费2秒钟(因为前端PC老旧,而执行操作很复杂),ASP 处理时间0.5 秒钟,COM+处理时间4秒钟,SQL Server处理时间0.5秒钟。
前端PC 数量太大,要升级成本太高。因此,大家都觉得先调后端吧,这时就算工程师花了九牛二虎之力,将三种服务器的性能都提升一倍,也就是让原来各服务器处理时间的总和5秒钟降为2.5秒钟,但系统整体时间还是要4.5秒钟。
用户骂了一个月之后,在不准更改功能的窘境下,还是要更新前端PC,这时大家就难堪了。所以,事前的整体评估很重要,告知用户能期待什么?最后底线是什么?才有可能让大家都接受调校的结果。
性能的基线应该都是可以量化的,例如,响应时间、单位时间可执行的批处理数量、单位时间可以处理的数据量、同时上线人数等,都可以求出最大值、最小值、平均值、总数等。针对要调校的目标,先获取数据后,才可以评估调校的方向是否正确。另外,对系统各环节的性能极限应尽可能地评估一下,不要耗了极大的功夫,才发现其实早已经把某一部分发挥到极限了,再怎么做都不可能提升多少性能,这时你可能需要变更用户需求、系统架构或必须更换软硬件。
有些值是当前可以算出来的,例如,直接将用户访问数据的T-SQL语句当前执行一遍,可以看出执行该语句的时间,在SQL Server本机上通过管理工具执行一次,在远程网络上再执行一次,可以约略知道网络是否有影响等。但某些数据可能要特别建立一些环境来测试,例如,没有用户,空机的时候某个工作的执行效率如何?有多人上线时,又是如何反应?原本某个工作每秒钟可以完成多少次,加上什么运行程序后,每秒钟只剩几次等。
另外,如压力测试时,要仿真多大的数据量,多少人同时上线等,建立这些基线的数据就较为困难,因为仿真的环境要尽量与真实相同。因为不同的数据模型,SQL Server 会建立不同的执行计划,若是以随机数产生的数据,往往与真正的数据类型不符,使索引判断、选择如何做Join等都会大不相同。
这些基线的数据应该越详尽越好,不要泛泛地取些值就拿来比较。笔者碰过一位工程师拿着代表某大型系统执行性能的4张图,上面标着中央处理器、主存储器、硬盘与网络,各有着一条弯弯曲曲描述性能的线,除了内存的线长时间在天上之外,其余的都不高,他就有了结论:内存要加大。当然,你让不懂信息技术的路人甲看这4张图,跟他解释图形的意义,问他要如何调性能,他也会说要加内存,因为就只有这张图看起来和其他3张长得不一样。
如果公司的钱用不完,这样的调校似乎就足够了,全部都靠扩大硬件来提升性能。但就前述的现象,可能要问的是,内存与硬盘缓存盘交换是否频繁,数据缓存区的高速缓存击中率(cache hit ratio)是否低于90% ,以进一步确认是否为内存不足才拖慢整体性能。说不定是数据库锁定,也说不定是程序有Bug造成内存遗失(memory leak),或是程序本身的Bug造成性能不足等。
若真的是内存不足,是否还可以调校?说不定是数据库系统的设置一开始要占用极大的缓存区,所以,大部分的内存都被它拿走,但整体来说并没有有效使用内存 。因此,哪个程序吃掉了大部分的资源?谁是主要调校的目标?什么样的方向或指针代表调校有效?诸此种种都应该落到文字上,如此可以整理较为清晰的思路,并有可讨论的交集,否则一堆没有共识的专家,恐怕只会众说纷纭,皆能证明不是自己的错,但祸首是谁却说不出来,最后落到会而不议,议而不决的窘况。
这些落于纸上的目标应越明确越好,例如上述的情况,若目标是 “我想要调低内存的使用率,因为它的值太高了”就不如“我想要调低某个程序开始获取内存的设置,因为它可能吃掉太多的内存,但实际没有用到这么多,而其他的应用程序没有足够的内存,导致整体系统性能不佳”。后者的描述有目标,且可以比较,因为实际调整后可以观察调低内存的程序执行起来是否有问题,整体的性能与没调整前是否有差异。
除了以文档描述基线、调校的目标外,还可以以文档描述所用的工具,如评估性能的程序、真实应用程序的片段功能、各种资源的性能监视程序、压力测试程序等。同时,有越详细的步骤越好。性能调校可能是一再的错误尝试,因为大部分的状况都是扑朔迷离的,无法一眼看出问题所在,需要改改这个,看看是否比较好,再修修那个,看看结果如何。若没有文档记录,你可能会在性能调校的大迷宫中打转,做一些类似而重复的事情,但总理不出头绪。
尝试列出系统中各个组件合理的性能消耗,可以帮助你理清整个系统访问中,各个组件所占的性能消耗比例,哪些部分有可以调整的空间。另外,再搭配调整该部分的成本有多高,让你了解调整的优先级,并对系统的极限有更佳的认识。