What is performance?

Salvatore Sanfilippo

什么是性能?

这篇博客文章的标题看起来是一个显然很容易回答的问题,不过,仔细想一想性能究竟意味着什么还是很有价值的:人们很容易混淆可扩展性和性能,而在数据库系统的具体场景中,将性能拆解为几个主要组成部分也并非易事。在这篇简短的博客文章中,我会写下目前我对数据库系统语境下性能的理解。

一个很好的起点,可能是我最近在 Redis 演讲中使用的第一张幻灯片。这张幻灯片实际上讲的就是性能,并指出性能主要包含三个不同的方面。

  1. 延迟:获取查询响应所需的时间。
  2. 每核心每单位时间的操作数:在给定的参考计算单元中,系统每秒能够响应多少个查询(操作)?
  3. 操作质量:这些操作能够完成多少工作?

延迟

这可能是性能最简单的组成部分。在许多应用中,人们希望系统返回响应所需的时间尽可能短。不过,平均耗时固然重要,延迟数值的可预测性,以及平均情况与最坏情况之间的差异,同样值得关注。使用得当时,内存系统能够提供非常出色的延迟特性,并且能够在一段时间内保持稳定的延迟。

每核心每秒的操作数

我列举的第二个组成部分,正是原始性能与可扩展性之间的区别所在。我们关注的是:对于给定的参考计算单元,系统在给定时间内能够完成多少工作。线性可扩展的系统可以通过使用多个节点,达到很高的每秒操作数;然而,这意味着它们具有可扩展性,并不一定意味着它们性能出色。

每核心每秒的操作数通常也与每瓦能够执行的查询数量相关,因此也关系到系统的能效。

操作质量

最后一点,虽然开发者通常不像重视吞吐量和延迟那样重视它,但在某些类型的系统中,尤其是内存系统中,它确实非常重要。

一个每秒能够执行 100 个操作、但操作“质量较差”的系统(例如从 Redis 的术语来说,只支持 GET 和 SET),其性能低于另一个在延迟和 OPS 特性相同的情况下还能够执行 INCR 操作的系统。比如,如果要解决的问题是递增计数器,那么前一个系统需要执行两次操作才能递增一个计数器(这里不考虑竞态条件),而提供 INCR 的系统只需执行一次操作。因此,后者实际上能够提供前者两倍的性能。

正如你所看到的,操作质量并不是一个绝对的衡量标准,而取决于要解决的问题类型。如果我们想要缓存 HTML 片段,那么这两个系统就是等价的,因为 INCR 操作在这种情况下毫无用处。

操作质量对于内存系统尤其重要,因为通常与接收命令、分发命令以及生成响应所需的时间相比,计算本身所占的时间微乎其微。因此,像 Redis 这样拥有丰富操作集合的系统,只需允许用户通过单个操作完成更多工作,就能在许多场景中几乎零成本地提供更好的性能。“完成更多工作”实际上可以意味着很多事情:既可以是回答更复杂的问题,例如 Redis 的 ZRANK 命令;也可以只是提供更具选择性的响应,例如 HMGET 命令,它能够只提供组成 Hash 值的部分字段的信息,从而减少服务器与客户端之间所需的带宽。

总体而言,操作质量的影响并不只是因为它们让系统每秒能够执行的操作具有更多或更少的价值,从而影响性能;操作质量还会直接影响延迟,因为更复杂的操作能够避免客户端与服务器之间为将多个简单操作组合成更复杂的计算而进行的多次数据往返传输。

结论

我希望这次对性能是什么的简短探讨,能够展现出从这一特定角度评估数据库系统能力时所涉及的一些复杂性。关于这个话题还有很多内容可以讨论,但我发现,上述三个性能组成部分是在评估一个系统,以及理解如何改造现有系统以改善其性能特性时,最有趣也最重要的几个方面。

感谢 Yiftach Shoolman(伊夫塔赫·舒尔曼)对这一话题提供的反馈。