单节点实例CPU利用率接近100%,QPS略低于1K

问题描述 投票:0回答:1

我正在评估 Spanner 的读取密集型用例。我正在使用 Postgres 方言。我有一个单节点设置(1000 个处理单元),其中一个表的行数少于一百万行。查表是通过主键是一个 sha256 编码的字符串来随机化键分布。在我的测试中,

我正在运行一个独立的 go-lang 客户端应用程序,该应用程序正在执行 100 个 go-routine 工作线程以使用主键查询数据库(select * from foo where ID IN('...', '...')) 。每个查询在 IN 子句中最多可查找 ID。

通过此设置,我获得了大约 1K QPS,CPU 达到 100%。 Spanner 宣称单个节点的 QPS 约为 22K,但我并没有达到这个水平。此设置中的最大扫描行数接近 20K,但平均扫描行数接近 2.5K。我什至不知道为什么最大扫描行是 20K,因为我总是只查询最多 10 个 ID 主键。 Spanner 后端指标仅在这个级别有用,但没有给我任何关于为什么我们无法超越 1K QPS 限制的指示。

我尝试了多次迭代,其中包括工作池大小、具有 10 个 gRPC 通道和批量大小的会话池(最大 1000)的多种变化,但结果或多或少是相同的。

感谢任何意见和指导并分享您的经验。

google-cloud-spanner
1个回答
0
投票

导致您看不到所需吞吐量的原因可能有多种。

客户

让我们从一些基础数学开始,看看您的client在此设置中可以处理的最大读取数是多少:

  1. Spanner 上的单次读取(使用主键选择单行),假设您使用的是一次性只读事务,将需要大约 4-5 毫秒。
  2. 你有 100 个 goroutine 读取数据。
  3. 每个 goroutine 每秒最多可执行 200 次读取(每次读取 5 毫秒,因此每 1,000 毫秒执行 200 次)。
  4. 这意味着您的客户端理论上应该能够每秒执行高达 20,000 次读取。您是否已验证基线确实符合这些数字?
  5. 换句话说:您是否验证过,当您只运行一个 goroutine 时,一次读取大约需要 5 毫秒?如果是这样,那么当 goroutine 数量达到多少时,性能就会开始下降?

查询

根据您的问题,您似乎正在生成一个包含随机文字列表的查询。所以类似

select * from foo where id in ('key1', 'key2', 'key3')
。这将要求 Spanner 在每次执行查询时解析和计划查询,因为每次执行的 SQL 字符串都不同。相反,您应该使用参数化查询,并将键作为参数值发送。这将使 Spanner 缓存查询计划,并且只需要解析和计划查询 10 次。

因此生成 10 个如下所示的查询:

select * from foo where id in ($1, $2, $3)

数据

您写道您的表包含“少于 100 万行”。 Spanner 是为规模而构建的,“更多”数据实际上比更少更好,因为它会让 Spanner 更好地分发数据。大约 1mio 行通常就足够了,但您的读取需要分布在整个键空间中才能实现最大吞吐量。您是否验证过您的随机密钥选择确实是随机的?您能否尝试在表中使用更多数据? 热身/持续时间

您的基准测试运行了多长时间?

Spanner 通过创建

splits

根据实际使用情况将数据分布在多个服务器上。这是一个动态的过程,需要一些时间。建议在生产启动之前预热数据库。对于基准也是如此。有关更多详细信息,请参阅 https://cloud.google.com/spanner/docs/pre-warm-database

© www.soinside.com 2019 - 2024. All rights reserved.