# 基准测试的策略

有两种主要的策略:

  1. 集成式(full-stack):针对整个系统的整体测试
  2. 单组件式(single-component):单独测试 MySQL

针对整个系统做集成测试,而不是单独测试 MySQL 的原因主要有以下几点:

  • 关注应用整体性能

    测试整个应用系统,包括 web 服务器、应用代码、网络和数据库是非常拥有的,因为用户关注的并不仅仅是 MySQL 本身的性能,而是应用整体性能。

  • MySQL 并非总是应用的瓶颈,通过整体的测试可以揭示这一点

  • 只有对应用做整体测试,才能发现各部分之间的缓存带来的影响

  • 整体应用的集成式测试更能揭示应用的真实表现,而单独组件的测试很难做到这一点

另外一方面,应用的整体基准测试很难建立,甚至很难正确设置。如果基准测试的设计有问题,那么意味着无法反应真实情况,从而基于此做的决策也就可能是错误的。

不过,有时候不需要了解整个应用的情况,而只需要关注 MySQL 的性能,至少在项目初期可以这样做。基于以下情况,可以选择只测试 MySQL:

  • 需要比较不同的 schema 或查询的性能
  • 针对应用中某个具体问题的测试
  • 为了避免漫长的基准测试,可以通过一个短期的基准测试,做快速的「周期循环」来检测出某些调整后的效果

另外,如果能够在 真实的数据集上执行重复的查询 那么针对 MySQL 的基准测试也是有用的,但是数据本身和数据集的大小都应该是真实的。如果可能,可以采用生产环境的数据快照。

不幸的是,设置一个基于真实数据的基准测试复杂而且耗时。往往不太可能得到一份生产数据集的拷贝。比如要测试的是一个刚开服的新应用,用户和数据都很少,如果想测试应用在规模扩张到很大以后的性能表现,就只能通过模拟大量的数据和压力来进行。

# 测试何种指标

在开始执行甚至是在设计测试之前,需要 先明确测试的目标。测试目标决定了 选择什么样的测试工具和技术,以获得精确而有意义的测试结果。可以将测试目标细化为一系列的问题,比如:

  • 这种 CPU 是否比另外一种要快?
  • 新索引是否比当前所有性能更好?

有时候需要用不同的方法测试不同的指标。比如针对 延迟(latency)吞吐量(throughput) 就需要采用不同的测试方法。请考虑以下指标,看看如何满足测试的需求。

  • 吞吐量:指单位时间内的事物处理数。

  • 响应时间或则延迟

    通常可以使用百分比响应时间来替代最大响应时间。例如:如果 95% 的响应时间都是 5 毫秒,则表示人物在 95% 的时间段内都可以在 5 毫秒之内完成

  • 并发性:在任意时间有多少同时发生的并发请求

  • 可扩展性:增加资源如多实例程序,能否增加他的吞吐量或者响应时间还是在可接受范围内

# 吞吐量

吞吐量指单位时间内的事物处理数。

这一直是经典的数据库应用测试指标。一些标准的基准测试被广泛的引用,如 TPC-C,而且很多数据库厂商都努力争取在这些测试中取得好成绩。这类基准测试主要针对 在线事物处理(OLTP)的吞吐量,非常适用于 多用户的交互式应用。 常用的测试单位是 每秒事物数(TPS),有些也采用 每分钟事物数(TPM)

# 响应时间或则延迟

用于测试任务所需的整体时间。

根据具体的应用,测试的时间单位可能是

  • 微秒

  • 毫秒、

  • 秒、

  • 分钟

根据不同的时间单位可以计算:

  • 出平均响应时间
  • 最小响应时间
  • 最大响应时间
  • 所占百分比

最大响应时间通常意义不大,因为测试时间越长,最大响应时间也可能越大。而且其结果通常不可重复,每次测试都可能得到不同的最大响应时间。因此,通常可以使用 百分比响应时间(percentile responset ime) 来替代最大响应时间。例如:如果 95% 的响应时间都是 5 毫秒,则表示人物在 95% 的时间段内都可以在 5 毫秒之内完成。

使用图表有助于理解测试结果:可以将测试结果绘制成 折线图(比如平均值折线或 95% 百分比折线)或 散点图,只管地表现数据结果集的分布情况。通过这些图可以发现长时间测试的趋势。(本章后续详细讨论这一点)

# 并发性

并发性是一个 非常重要 又经常被 误解和误用 的指标。

比如:它经常被标识成多少用户在同一时间浏览一个 web 站点,经常使用的指标是有多个少会话。HTTP 协议是无状态的,大多数用户只是简单的读取浏览器上显示的信息,这并不等同于 web 服务器的并发性。

Web 服务器的并发性更准确的度量指标,应该是 在任意时间有多少同时发生的并发请求

在应用的不同环节都可以测量相应的并发性。Web 服务器的高并发,一般也会导致数据库的高并发,单服务器采用的语言和工具集对此都会有影响。注意 不要将创建数据库连接和并发性搞混淆。一个设计良好的应用,同时可以打开成败上千个 MySQL 数据库服务器链接,但可能同时只有少数链接在执行查询。所以说,一个 Web 站点「同时有 5 万个用户」访问,缺可能只有 10~15 个并发请求到 MySQL 数据库。

换句话说,并发性基准测试需要关注的是 正在工作中的并发操作,或则是 同时工作中的线程数或则连接数。当并发性增加时,需要 测量吞吐量是否下降,响应时间是否变成,如果是这样,应用可能就无法处理峰值压力。

并发性的策略完全不同于响应时间和吞吐量。它不像是一个结果,而更像是设计基准测试的一种属性。并发性测试 通常不是为了测试应用能达到的并发度,而是为了 测试应用在不同并发下的性能。当然,数据库的并发性还是需要测量的。可以通过 sysbench 指定 32、64 或则 128 个线程测试,然后在测试期间记录 MySQL 数据库的 Threads_runing 状态值。(在第 11 章将讨论这个指标对容量规划的影响)

# 可扩展性

在系统的业务压力可能发生变化的情况下,测试可扩展性就非常有必要了。

第 11 章将更进一步讨论该话题。简单说:可扩展指的是,给系统增加一倍的工作(这个理解不了是什么),在理想情况下就能获得两倍的结果(即吞吐量增加一倍)。或则说,给系统增加一倍的资源(比如两倍的 CPU 数),就可以获得两倍的吞吐量。同时 性能(响应时间) 也必须在可以接受的范围内。大多数系统是无法做到如此理想的线性扩展的。随着压力的变化,吞吐量和性能都可能 越来越差。

可扩展性指标对于容量规范非常有用,它可以提供其他测试无法提供的信息,来帮助发现应用瓶颈。

比如:系统是基于单个用户的响应时间测试(很糟糕的测试策略)设计的,虽然测试结果很好,但并发度增加时,系统的性能有可能变得非常糟糕。而一个基于不断增加用户连接的情况下的 响应时间测试则可以发现这个问题。

一些任务,比如从细粒度数据创建汇总表的批量工作,需要的是 周期性的快速响应时间。当然有可以测试这些任务纯粹的响应时间,单要注意考虑这些任务之间的相互影响。批量工作可能导致相互之间有影响的查询性能变差,反之亦然。

# 最后

归根揭底,应该测试那些对用户来说最重要的指标。因此应该尽可能地区收集一些需求,比如,什么样的响应时间是可以接受的,期待多少的并发性,等等。然后基于这些需求来设计基准测试,避免目光短浅的只关注部分指标,而忽略其他指标