在注意到我们的数据库已成为我们实时生产系统的主要瓶颈后,我决定构建一个简单的基准来查明问题的根源。
基准:我计算了将 InnoDB 表中的同一行增加 3000 次所需的时间,其中该行由其主键索引,并且正在更新的列不属于任何索引。我使用远程机器上运行的 20 个并发客户端执行这 3000 次更新,每个客户端都有自己独立的数据库连接。
我有兴趣了解为什么我进行基准测试的不同存储引擎 InnoDB、MyISAM 和 MEMORY 具有它们所做的配置文件。我也希望了解为什么 InnoDB 相比之下表现如此糟糕。
InnoDB(20 个并发客户端):每次更新耗时 0.175s。所有更新均在 6.68 秒后完成。
MyISAM(20 个并发客户端):每次更新需要 0.003 秒。所有更新都在 0.85 秒后完成。
内存(20 个并发客户端):每次更新耗时 0.0019 秒。所有更新都在 0.80 秒后完成。
考虑到并发性可能会导致这种行为,我还对单个客户端执行 100 次顺序更新进行了基准测试。
InnoDB:每次更新需要 0.0026 秒。
MyISAM:每次更新需要 0.0006 秒。
内存:每次更新需要 0.0005 秒。
实际机器是一个 Amazon RDS 实例 ( http://aws.amazon.com/rds/ ),大部分是默认配置。
我猜答案将如下所示:每次更新后的 InnoDB fsyncs(因为每次更新都是符合 ACID 的事务),而 MyISAM 不支持,因为它甚至不支持事务。MyISAM 可能在内存中执行所有更新,并定期刷新到磁盘,这就是它的速度接近 MEMORY 存储引擎的方式。如果是这样,有没有办法使用 InnoDB 来支持它的事务,但也许可以放松一些约束(通过配置),以便以一些持久性为代价更快地完成写入?
另外,随着客户数量的增加,关于如何提高 InnoDB 性能的任何建议?它的扩展性显然比其他存储引擎差。
更新
我找到了https://blogs.oracle.com/MySQL/entry/comparing_innodb_to_myisam_performance,这正是我想要的。设置 innodb-flush-log-at-trx-commit=2 允许我们在发生电源故障或服务器崩溃的情况下放松 ACID 约束(每秒刷新一次磁盘)。这为我们提供了与 MyISAM 类似的行为,但我们仍然可以从 InnoDB 中可用的事务功能中受益。
运行相同的基准测试,我们看到写入性能提高了 10 倍。
InnoDB(20 个并发客户端):每次更新耗时 0.017 秒。所有更新都在 0.98 秒后完成。
还有其他建议吗?