- 基准测试(benchmark)是MySQL新手和专家都需要掌握的一项基本技能。简单地说,基准测试是针对系统设计的一种压力测试。通常的目标是为了掌握系统的行为。但也有其他原因,如重现某个系统状态,或者做新硬件的可靠性测试。
2.1 为什么需要基准测试
- 基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法。
- 基准测试可以观察系统在不同压力下的行为,评估系统的容量,掌握哪些是重要的变化,或者观察系统如何处理不同的数据。
- 基准测试可以在系统实际负载之外创造一些虚构场景进行测试。还可以用于其它目的,比如为应用创建单元测试套件。
- 基准测试的一个主要问题在于其不是真实压力的测试。
- 基准测试只能进行大概的测试,来确定系统大致的余量有多少。当然也可以做一些真实压力测试(和基准测试有区别),但在构造数据集和压力的时候要特别小心,而且这样就不再是基准测试了。基准测试要尽量简单直接,结果之间容易相互比较,成本低且易于执行。尽管有诸多限制,基准测试还是非常有用的(只要搞清楚测试的原理,并且了解如何分析结果所代表的意义)。
2.2 基准测试的策略
- 基准测试有两种主要的策略:一是针对整个系统的整体测试,另外是单独测试MySQL。这两种策略也被称为集成式(full-stack)以及单组件式(single-component)基准测试。
2.2.1 测试何种指标
- 在开始执行甚至是在设计基准测试之前,需要先明确测试的目标。测试目标决定了选择什么样的测试工具和技术,以获得精确而有意义的测试结果。
考虑以下指标,选择如何满足测试的需求
吞吐量
吞吐量指的是单位时间内的事务处理数。这一直是经典的数据库应用测试指标。这类基准测试主要针对在线事务处理(OLTP)的吞吐量,非常适用于多用户的交互式应用。常用的测试单位是每秒事务数(TPS),有些也采用每分钟事务数(TPM)。响应时间或者延迟
这个指标用于测试任务所需的整体时间。根据具体的应用,测试的时间单位可能是微秒、毫秒、秒或分钟。根据不同的时间单位可以计算出平均响应时间、最小响应时间、最大响应时间和所占百分比。最大响应时间通常意义不大,因为测试时间越长,最大响应时间也可能越大。而且其结果通常不可重复,每次测试都可能得到不同的最大响应时间。因此,通常可以使用百分比响应时间(percentile response time)来替代最大响应时间。并发性
并发性是一个非常重要又经常被误解和误用的指标。例如,它经常被表示成多少用户在同一时间浏览一个Web站点,经常使用的指标是有多少个会话。然而,HTTP协议是无状态的,大多数用户只是简单地读取浏览器上显示的信息,这并不等同于Web服务器的并发性。而且,Web服务器的并发性也不等同于数据库的并发性,而仅仅只表示会话存储机制可以处理多少数据的能力。Web服务器的并发性更准确的度量指标,应该是在任意时间有多少同时发生的并发请求。
在应用的不同环节都可以测试响应的并发性。Web服务器的高并发,一般也会导致数据库的高并发,但服务器采用的语言和工具集对此都会有影响。注意不要将创建数据库连接和并发性搞混淆。一个设计良好的应用,同时可以打开成百上千个MySQL数据库服务器连接,但可能同时只有少数连接在执行查询。所以说,一个Web站点“同时有50000个用户”访问,却可能只有10~15个并发请求到MySQL数据库。
换句话说,并发性基准测试需要关注的是正在工作中的并发操作,或者是同时工作中的线程数或者连接数。当并发性增加时,需要测试吞吐量是否下降,响应时间是否变长,如果是这样,应用可能就无法处理峰值压力。
并发性的测量完全不同于响应时间和吞吐量。它不像是一个结果,而更像是设置基准测试的一种属性。并发性测试通常不是为了测试应用能达到的并发度,而是为了测试应用在不同并发下的性能。当然,数据库的并发性还是需要测量的。可以通过sysbench指定32、64或128个线程的测试,然后在测试期间记录MySQL数据库的Threads_running状态值。可扩展性
在系统的业务压力可能发生变化的情况下,测试可扩展性就非常必要了。简单地说,可扩展性指的是,给系统增加一倍的工作,在理想情况下就能获得两倍的结果(即吞吐量增加一倍)。或者说,给系统增加一倍的资源(比如两倍的CPU数),就可以获得两倍的吞吐量。当然,同时性能(响应时间)也必须在可以接受的范围内。大多数系统是无法做到如此理想的线性扩展的。随着压力的变化,吞吐量和性能都可能越来越差。
可扩展性指标对于容量规范非常有用,它可以提供其他测试无法提供的信息,来帮助发现应用的瓶颈。
归根结底,应该测试那些对用户来说最重要的指标。因此应该尽可能地去收集一些需求,比如,什么样的响应时间是可以接受的,期待多少的并发性,等等。然后基于这些需求来设计基准测试,避免目光短浅地只关注部分指标,而忽略其他指标。
2.3 基准测试方法
以下常见错误可能导致测试结果无用或者不精确
1. 使用真实数据的子集而不是全集。
2. 使用错误的数据分布。
3. 使用不真实的分布参数。
4. 在多用户场景中,只做单用户的测试。
5. 在单服务器上测试分布式应用。
6. 与真实用户行为不匹配。
7. 反复执行同一个查询。
8. 没有检查错误。基准测试完成后,一定要检查一下错误日志,这应该是基本的要求。
9. 忽略了系统预热(warm up)的过程。
10. 使用默认的服务器配置。
11. 测试时间太短。
如果其他条件相同,就应努力使测试过程尽可能地接近真实应用的情况。
2.3.1 设计和规划基准测试
- 规划基准测试的第一步是提出问题并明确目标。然后决定是采用标准的基准测试,还是设计专用的测试。
- 如果采用标准的基准测试,应该确认选择了合适的测试方案。
- 设计专用的基准测试是很复杂的,往往需要一个迭代的过程。首先需要获得生产数据集的快照,并且该快照很容易还原,以便进行后续的测试。然后,针对数据运行查询。可以建立一个单元测试集作为初步的测试,并运行多遍。但是这和真实的数据库环境还是有差别的。更好的办法是选择一个有代表性的时间段,记录生产系统上的所有查询。如果时间段选得比较小,则可以选择多个时间段。这样有助于覆盖整个系统的活动状态。
- 可以在不同级别记录查询。如果是集成式(full-stack)基准测试,可以记录Web服务器上的HTTP请求,也可以打开MySQL的查询日志(Query Log)。倘若要重演这些查询,就要确保创建多线程来并行执行,而不是单个线程线性地执行。对日志中的每个连接都应该创建独立的线程,而不是将所有的查询随机地分配到一些线程中。查询日志中记录了每个查询是在哪个连接中执行的。
- 即使不需要创建专用的基准测试,详细地写下测试规划也是必需的。测试可能要多次反复运行,因此需要精确地重现测试过程,而且也要考虑到下次测试不是同一个人的情况。
- 应该建立将参数和结果文档化的规范,每一轮测试都必须进行详细记录。需要记住的是,经常要写一些脚本来分析测试结果,因此如果能够不用打开文档等额外操作,当然是更好的。
2.3.2 基准测试应该运行多长时间
- 基准测试应该运行足够长的时间,这一点很重要。有时候无法确认测试需要多长的时间才足够,如果这样可以让测试一直运行,持续观察直到确认系统已经稳定。一个简单的测试规则,就是等系统看起来稳定的时间至少等于系统预热的时间。
- 一个常见的错误的测试方式是,只执行一系列短期的测试,例如每次60秒的测试,就在此基础上去总结系统的性能。如果不能自己进行长时间的测试,与其用短时间的测试结果来评断,不如参考别人的测试结果。
扩展基准测试的I/O性能图
2.3.3 获取系统性能和状态
- 在执行基准测试时,需要尽可能多地手机被测试系统的信息。使用shell脚本,尽可能多的收集数据,多余一些数据总比缺乏重要的数据要好。需要记录的数据包括系统状态和性能指标。
- 先收集所有的原始数据,然后再基于此做分析和过滤是一个好习惯。如果在收集的时候就对数据做预处理,而后续分析发现一些异常的地方需要用到更多的原始数据,就“抓瞎”了。
2.3.4 获得准确的测试结果
- 获得准确测试结果的最好办法,是回答一些关于基准测试的基本问题:是否选择了正确的基准测试?是否为问题收集了相关的数据?是否采用了错误的测试标准?
- 接着,确认测试结果是否可重复。每次重新测试之前要确保系统状态的一致,甚至有必要重启系统并预热,还需要确保预热的时间足够长,并可重复。如果预热采用的随机查询,那么测试结果可能就是不可重复的。
- 每次测试要保证测试数据相同,一个确保物理磁盘数据的分布尽可能一直的办法是,每次都进行快速格式化并进行磁盘分区复制。
- 每次测试中,修改的参数应该尽量少,有时参数之间的依赖性会给测试带来复杂性。一般情况下,都是通过迭代逐步地修改基准测试的参数,而避免每次运行都做大量的修改。
- 基于MySQL默认配置的测试没有什么意义。
- 如果测试中出现异常结果,不要轻易当作坏数据点而丢弃。分析这些异常结果,偶尔也会获得意想不到的收获。
2.3.5 运行基准测试并分析结果
- 通常来说,自动化基准测试可以获得更精确的测试结果。要尽可能地使所有测试过程都自动化,包括装载数据、系统预热、执行测试、记录结果等。
- 基准测试通常要运行多次,以提高测试结果的准确度。
- 获得测试结果后,还需要对结果进行分析,最终目的是回答在设计测试时的问题。
- 如何从数据中抽象出有意义的结果,依赖于如何收集数据。通常使用脚本来分析数据,不仅减轻分析的工作量,也易于文档化。
2.3.6 绘图的重要性
- 在执行基准测试的时候尽可能地收集更多的细节数据,然后将数据绘制成图形,这样可以帮助快速地发现问题。
2.4 基准测试工具
2.4.1 集成式测试工具
- ab:ab是一个Apache HTTP服务器基准测试工具。它可以测试HTTP服务器每秒最多可以处理多少请求。
- http_load:这个工具概念上和ab类似,也被设计为对Web服务器进行测试,但比ab要更加灵活。可以通过一个输入文件提供多个URL,http_load在这些URL中随机选择进行测试。
- JMeter:JMeter是一个Java应用程序,可以加载其他应用并测试其性能。JMeter比ab和http_load都要复杂得多。
2.4.2 单组件式测试工具
- mysqlslap:mysqlslap可以模拟服务器的负载,并输出计时信息。测试时可以执行并发连接数,并指定SQL语句,如果没有指定SQL语句,mysqlslap会自动生成查询schema的SELECT语句。
- MySQL Benchmark Suite(sql-bench):可以用于在不同数据库服务器上进行比较测试。它是单线程的,主要用于测试服务器执行查询的速度,结果会显示哪种类型的操作在服务器上执行得更快。
- Super Smack:Super Smack是一款用于MySQL和PostgreSQL的基准测试工具,可以提供压力测试和负载生成。这是一个复杂而强大的工具,可以模拟多用户访问,可以加载测试数据到数据库,并支持使用随机数据填充测试表。
- Database Test Suite:这是一款类似某些工业标准测试的测试工具集,其中的dbt2就是一款免费的TPC-C OLTP测试工具(未认证)。
- Percona’s TPCC-MySQL Tool:一个类似TPC-C的基准测试工具集,其中有部分是专门为MySQL测试开发的。
- sysbench:sysbench是一款多线程系统压测工具,它可以根据影响数据库服务器性能的各种因素来评估系统的性能。sysbench是一种全能测试工具,支持MySQL、操作系统和硬件的硬件测试。
2.5 基准测试案例(P52~P65)
2.6 总结
- 每个MySQL的使用者都应该了解一些基准测试的知识。
- 基准测试不仅仅是用来解决业务问题的一种时间行动,也是一种很好的学习方法。
- 如果你还没有做过基准测试,那么建议至少要熟悉sysbench。可以先学习如何使用OLTP和FILEIO测试。OLTP基准测试可以很方便地比较不同系统的性能。另一方面,文件系统和磁盘基准测试,则可以在系统出现问题时有效地诊断和隔离异常的组件。
- 如果经常执行基准测试,那么指定一些原则是很有必要的。选择一些合适的测试工具并深入地学习。可以建立一个脚本库,用于配置基准测试,收集输出结果、系统性能和状态信息,以及分析结果。