在 MySQL 服务器中如何统计表的行数

让我们了解有哪些可用选项可以获取 MySQL 表中行的准确数字或者估计值。
获取表中准确行数的选项是执行:

SELECT COUNT(*) FROM [table];

在 MyISAM 中,当没有提供 WHERE 子句时,此操作非常快,因为存储引擎随时知道表中有多少行。
相反,在处理 InnoDB 存储引擎时,没有可用的计数器。
这是由于此存储引擎的事务性质。
该主题在官方文档中得到解决:

InnoDB 不保留表中行的内部计数,因为并发事务可能同时“看到”不同数量的行。
因此,SELECT COUNT(*) 语句只计算对当前事务可见的行。

在 MySQL 5.7.18 之前,InnoDB 通过扫描聚集索引来处理 SELECT COUNT(*) 语句。
从 MySQL 5.7.18 开始,InnoDB 通过遍历较小的二级索引(如果存在)来处理 SELECT COUNT(*) 语句。

如果索引记录不完全在缓冲池中,则处理 SELECT COUNT(*) 语句需要一些时间。
为了更快地计数,我们可以创建一个计数器表并让应用程序根据它所做的插入和删除来更新它。
但是,在数千个并发事务启动对同一计数器表的更新的情况下,此方法可能无法很好地扩展。
如果近似行数足够,则可以使用 SHOW TABLE STATUS。

InnoDB 以相同的方式处理 SELECT COUNT(*) 和 SELECT COUNT(1) 操作。
没有性能差异。

因此,从 MySQL Server 5.7.18 开始,可以为 InnoDB 表添加二级索引以改进索引扫描。
也可以将行计数存储在不同的表中并使用触发器更新它(当添加/删除记录时,触发器将从计数器添加或者保留“1”)。

或者,如果对 InnoDB 表的行数进行粗略估计就足够了:

  • 可以使用计划任务计算它并将其存储在不同的表中。
  • 另一个近似值是从 INFORMATION_SCHEMA.TABLES 中获取 TABLE_ROWS。这个估计是基于表中随机页面的抽样(其准确性由 innodb_stats_persistent_sample_pages 决定)。

MySQL 8.0 在这方面提供了另外的改进:

  • MySQL 8.0.13 提高了 InnoDB 表上 COUNT(*) 查询的性能(没有条件/分组等),因为优化器将被允许选择适当的索引来计算行数
  • MySQL 8.0.14 InnoDB 现在支持并行聚集索引读取,可以改进 SELECT COUNT(*) 子句。这是通过 innodb_parallel_read_threads 配置参数实现的。
日期:2020-09-17 00:11:07 来源:oir作者:oir