谷歌云SQL速度慢:配置有10GB RAM的mysql实例比配备125MB RAM的Macbook Pro慢20倍

8
我们按照Google Cloud SQL的说明清空了我们的表,并将其导入到第二代Google Cloud SQL实例中。
我们非常期待看到我们的数字在“谷歌硬件”上运行的情况。
通过使用Apache的ab进行Rails应用程序的压力测试,我们发现完成时间比预期慢了150毫秒,而且我们注意到ActiveRecord在相同页面上比我们的生产服务器(裸机)多花费了30毫秒到50毫秒的时间。
当我们深入挖掘时,真正令我们惊讶的是像这样的简单计数查询:
GOOGLE CLOUD SQL - db-n1-standard-4 (4vcpu and 15GB RAM)

1. Cold query

mysql> SELECT COUNT(*) FROM `event_log`;
+----------+
| COUNT(*) |
+----------+
|  3998050 |
+----------+
1 row in set (19.26 sec)

2. Repeat query

mysql> SELECT COUNT(*) FROM `event_log`;
+----------+
| COUNT(*) |
+----------+
|  3998050 |
+----------+
1 row in set (1.16 sec)

SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+------------------------------------------+
| @@innodb_buffer_pool_size/1024/1024/1024 |
+------------------------------------------+
|                          10.500000000000 |
+------------------------------------------+
1 row in set (0.00 sec)



我可以多次重复查询,性能相同。 在我的 MacBook Pro 2017 上运行相同的查询,使用完全相同的转储:
MACBOOK PRO 2017

1. Cold query

mysql> SELECT COUNT(*) FROM `event_log`;
+----------+
| COUNT(*) |
+----------+
|  3998050 |
+----------+
1 row in set (1.51 sec)

2. Repeat query

mysql> SELECT COUNT(*) FROM `event_log`;
+----------+
| COUNT(*) |
+----------+
|  3998050 |
+----------+
1 row in set (0,51 sec)

SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+------------------------------------------+
| @@innodb_buffer_pool_size/1024/1024/1024 |
+------------------------------------------+
|                           0.125000000000 |
+------------------------------------------+
1 row in set (0,03 sec)




更荒谬的是,正如您在上面看到的那样,我从未对默认的mysql安装进行任何调整,因此它仅在我的Macbook上使用125MB的RAM,而Google Cloud实例可用的RAM为10GB。
我们尝试将Google Cloud SQL实例大小增加到db-n1-highmen-8(8vCPU和52GB RAM!),但性能没有提高(如果我们从db-n1-standard-4降低,我们会看到性能下降)。
最后,使用这个问题,我们可以确认我们的数据库只有46GB,但在导入期间,Google Cloud SQL中的存储使用量不断增长,直到达到荒谬的74GB……我们不知道这是否是由于二进制日志记录(在Google Cloud SQL上默认启用,在我的本地机器上关闭)。
那么……有没有人在生产中使用Google Cloud sql? :)
更新:我们使用完全相同的.sql转储,并将其加载到一个db.r4.large AWS RDS中(因此具有相同的CPU / RAM),并在查询中获得了一致的0.50秒性能,并且也没有超过46GB的实例。

Binlog就是罪魁祸首。这个超级用户问答页面上的问题是:MySQL的二进制日志记录是否会导致性能下降? - Hackerman
@黑客大侠 不是的。我们关闭了二进制日志记录(控制台中有一个简单的复选框),在重启后这些是结果:第一个COUNT(我称之为“冷查询”):9.84秒;其他计数(尝试> 10次并获得一致结果):平均1.14秒。 - sandre89
嘿,伙计,我也遇到了同样的问题。有什么解决办法吗?在我的情况下,我使用Digital Ocean的外部服务器,并且当我将Google Cloud SQL连接到我的应用程序时,我发现它非常缓慢。 - Nico Zarris
@NicoZarris,由于我们正在比较AWS和Google Cloud,我们决定暂时选择AWS,并没有深入挖掘(请参见更新的问题,在AWS中,我们从一开始就拥有了最佳性能)。令人沮丧的是,在南美洲,AWS的带宽成本比GC高出2倍以上。 - sandre89
此外,Google Cloud SQL for MySql 默认使用 GTID 复制,这可能是性能缓慢的一个重要因素。https://cloud.google.com/sql/docs/mysql/1st-2nd-gen-differences - Raj
1个回答

5
比较执行计划(在代码前加上“EXPLAIN”)后,您可能会发现一些显著的实现差异,这是由于配置参数变化超出了缓冲池大小所致。我在周末使用Postgres Cloud SQL数据库遇到了类似的问题,该数据库包含约100GB的数据,并镜像了我的MacBook Pro本地数据库。对于使用索引进行极其有针对性的选择时,性能与我的本地数据库相当,但是扫描非微不足道数量的数据的查询速度要慢2-5倍。
比较本地和云端实例的配置结果(在MySQL中是“SHOW VARIABLES”),我注意到了一些不同,例如Cloud SQL上的“max_parallel_workers_per_gather”= 0,而我的本地实例为2。
对于“select count(*)...”的情况,将“max_parallel_workers_per_gather”设置> 0允许对多个worker并行顺序扫描的结果执行Gather操作;将其设置为零,则引擎必须执行单个顺序扫描。对于其他查询,我也注意到了类似的趋势,在我的本地数据库中使用了并行工作线程,成本更低,速度更快,而在云端实例中未使用。
这只是一个影响因素;我相信深入挖掘设置会找到更多这样的解释。这些是托管服务所带来的权衡(尽管能够对此类参数有更多控制会更好)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接