在某个时间点之后,来自 Go 的连续 MySQL 查询变得慢得多

我正在写一份工作,它通过一些 MySQL 表,根据一些标准选择一些行,从中提取电子邮件地址并向每个人发送电子邮件。


过滤过程查看一个storage非常大(大约 6gb 转储)的表(我们称之为),看起来像这样:


Columns:

id      varchar(64) PK

path    varchar(64) PK

game    varchar(64)

guid    varchar(64)

value   varchar(512)

timestamp   timestamp

有两个索引:((id, path)如上所示的 PK)和guid.


该作业首先从一个表中检索一长串 guid,然后对它们进行批处理并在storage表上执行如下连续查询:


SELECT guid, timestamp FROM storage 

WHERE game = 'somegame' 

AND path = 'path' AND value = 'value' AND timestamp >= '2015-04-22 00:00:00.0' AND timestamp <= '2015-04-29T14:53:07+02:00' 

AND guid IN ( ... )

其中IN子句包含 guid 列表。


我需要检索时间戳才能进一步过滤。


在我的本地 MySQL 上运行时,一切都按预期工作,查询需要大约 180 毫秒,批量为 1000 个 guid。


当针对 Amazon RDS 上的同一个数据库运行时,查询开始很快,但在某个时间点后,它们突然开始花费大约 30 秒,并继续这样做直到作业结束。

我已经尝试了很多方法来解决这个问题,但无法找出原因。一些注意事项:

  • 该作业仅使用一个sql.DB对象。此外,我准备了一次上述语句并大量重复使用它。

  • 一开始以为是因为RDS DB跑的是MySQL 5.5,我跑的是5.6。我制作了 RDS DB 的副本,升级到 5.6,再次运行该作业。问题又发生了。

  • 两个数据库中的数据量相同:我转储了生产数据库并将其导入到我的本地数据库中并运行了作业。相同的行为(它仍然在本地快速运行)。

  • RDS 节点的 AWS 监控未显示任何显着峰值。CPU 使用率从 1% 跃升至 10%,而且该作业似乎只打开了几个连接 (~4)。

  • 我让一位同事在他们的 PC 上运行该作业,指向我的MySQL 数据库,只是为了确保出色的性能并非源于连接是本地的。它的运行速度与在我的 PC 上一样快(不可否认,通过 LAN)。

  • 我在本地 PCAmazon EC2 节点上针对 RDS 运行了该作业,该节点与 RDS 非常接近。从EC2来看,它表现得更好,但问题仍然出现。

  • 作业是非常并发的,每一步都有输入和输出通道(缓冲区大小为 1000),工作由 goroutines 执行。在这些步骤之间,我还有其他 goroutine 可以批量处理前一个 goroutine 的输出。

  • 减速是突然的,一个查询需要几毫秒,下一个需要几十秒。

我不知道为什么会发生这种情况。任何建议,将不胜感激。


拉丁的传说
浏览 240回答 1
1回答

ITMISS

所以,经过大量的实验,我找到了解决方案。我在所涉及的 RDS 实例上使用磁性存储,这保证了大约 100 IOPS。这限制了我们查询数据的速度。我使用 2000&nbsp;Provisioned IOPS进行了测试,并且该作业一直运行得很快。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go