为什么在解释知道答案时count(*)慢?


14

这个查询:select count(*) from planner_event需要很长时间才能运行-这么长的时间,我放弃并杀死了它。但是,当我运行时explain select count(*) from planner_event,我可以在输出中看到一列带有行数(14m)的列。

为什么解释可以立即获得行数,但是count(*)需要很长时间才能运行?


没有WHERE原因的COUNT(*)将导致对InnoDB引擎的表扫描。MyISAM可以直接传递计数,因为COUNT保留在表的头文件中。
雷蒙德·尼兰

Answers:


16

说明正在使用先前收集的统计信息(由查询优化器使用)。做一个select count(*)读操作,每数据块。

这是一种获取估算的行数的廉价方法:

select TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='planner_event';

即使您这样做了select count(id),它可能仍会花费很长时间,除非您具有辅助索引id(也假定id是PRIMARY KEY)。因为所有数据(包括行数据)都存储在B树索引中,所以执行a select count(PK_COLUMN)仍然是相当数量的IO(需要读取所有数据页)。如果您在PK字段上有二级索引,它将能够执行较少的IO来执行计数。


I_S.TABLES给您的估计值EXPLAIN给您的估计值相同。
瑞克·詹姆斯

查询丢失AND TABLE_SCHEMA='my_database',否则,如果在另一个数据库中有一个具有相同名称的表,则将返回多个结果。
cz

3

解释从一些“统计信息”中获取数字,这些统计信息用于估算优化器的情况。该数字可能不正确-我有时会看到它比实际值大2倍(更高或更低)。

COUNT(*)在InnoDB表上执行,必须扫描该表,以避免对其他连接正在忙于插入/删除但尚未“提交”的记录进行错误计数。实际上,对某个索引进行完全扫描就足够了,而不必对整个表(包含进行扫描PRIMARY KEY)。

你有多少RAM?的值是innodb_buffer_pool_size多少?如果那大约占RAM的70%,可能会有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.