Cra*_*ite 4 mysql performance innodb mysql-slow-query-log
我们有一个包含数百万个条目的大表。完整计数非常慢,请参见下面的代码。这对于 MySQL InnoDB 表来说很常见吗?难道就没有办法加速这个过程吗?即使使用查询缓存,它仍然“慢”。我还想知道,为什么具有 2.8 mio 条目的“通信”表的计数比具有 4.5 mio 条目的“事务”表的计数慢。
我知道使用 where 子句会快得多。我只是想知道表现不佳是否正常。
我们使用 Amazon RDS MySQL 5.7 和 m4.xlarge(4 个 CPU、16 GB RAM、500 GB 存储)。我也已经尝试过使用更多 CPU 和 RAM 的更大实例,但查询时间没有大的变化。
mysql> SELECT COUNT(*) FROM transaction;
+----------+
| COUNT(*) |
+----------+
| 4569880 |
+----------+
1 row in set (1 min 37.88 sec)
mysql> SELECT COUNT(*) FROM transaction;
+----------+
| count(*) |
+----------+
| 4569880 |
+----------+
1 row in set (1.44 sec)
mysql> SELECT COUNT(*) FROM communication;
+----------+
| count(*) |
+----------+
| 2821486 |
+----------+
1 row in set (2 min 19.28 sec)
Run Code Online (Sandbox Code Playgroud)
这是使用支持多版本并发控制(MVCC)的数据库存储引擎的缺点。
\n\nInnoDB 允许您的查询在事务中隔离,而不会阻塞正在读取和写入数据行的其他并发客户端。这些并发更新不会影响您的事务的数据视图。
\n\n但是,考虑到在进行计数时许多行正在添加或删除,表中的行数是多少?答案是模糊的。
\n\n您的事务不应能够“查看”事务启动后创建的行版本。同样,即使其他人请求删除行,您的事务也应该对行进行计数,但他们是在您的事务开始后这样做的。
\n\n答案是,当您执行SELECT COUNT(*)\xe2\x80\x94\xc2\xa0 或任何其他类型的查询需要检查许多行 \xe2\x80\x94 InnoDB 必须访问每一行,以查看哪个是当前版本该行对数据库的事务视图可见,如果可见则对其进行计数。
在不支持事务或并发更新的表(例如 MyISAM)中,存储引擎将行总数保留为表的元数据。该存储引擎不支持多个线程同时更新行,因此总行数不太模糊。因此,当您从 MyISAM 表请求时,它只返回内存中的行数(但如果您使用 WHERE 子句按某些条件计算某些行子集,则SELECT COUNT(*)这没有用,因此它实际上必须SELECT COUNT(*)在这种情况下计算它们)。
总的来说,大多数人认为 InnoDB 对并发更新的支持非常值得,并且他们愿意牺牲SELECT COUNT(*).