SELECT COUNT(*) with GROUP BY 对于大表来说很慢

Posted

技术标签:

【中文标题】SELECT COUNT(*) with GROUP BY 对于大表来说很慢【英文标题】:SELECT COUNT(*) with GROUP BY slow for large table 【发布时间】:2013-02-12 11:16:37 【问题描述】:

我有一个包含大约 1 亿行的表,其中包含三列(全部为 INT):

id | c_id | l_id

即使我使用索引,甚至是基本的

select count(*), c_id 
from   table 
group by c_id;

需要 16 秒 (MYISAM) 到 25 秒 (InnoDB) 才能完成。

有没有什么方法可以在不跟踪单独表中的计数的情况下加快这个过程(例如,通过使用触发器)?

/edit: 所有列都有索引

【问题讨论】:

这张桌子上有什么索引? 如果您需要计数,您可以简单地使用 count(id) 为什么使用 *.请避免使用 * 而是始终使用列。 @raheel shan,你错了,如果c_id被索引了,count(id)会比较慢,看我的回答执行计划 每一列都有一个索引。正如迈克尔所说,count(id) 比较慢(大约 8 倍) 【参考方案1】:

查看执行计划以了解执行相同查询的可能方法SqlFiddle,

如果c_id 没有在我提供的测试集上编入索引,SELECT COUNT(id) 会更快。

否则您应该使用COUNT(*),因为查询中可能不会使用索引优化。

它还取决于数据库中的行数和 ENGINE 类型,因为 mysql 也会根据这一事实决定什么更好。

在执行查询之前,您应该始终看到查询的执行计划,方法是在选择前输入EXPLAIN

我不得不说,在大多数情况下,在大数据集上,COUNT(*)COUNT(id) 应该会产生相同的执行计划。

【讨论】:

【参考方案2】:

导致性能问题的不是 Count(*),而是对 1 亿行进行分组。

你应该在 c_id 列上添加一个索引

【讨论】:

一开始忘了提到索引是存在的。虽然count(*) 在使用 MyISAM 时可能不是问题,但它肯定会在 InnoDB 上与 InnoDB 一起使用(单独执行 count(*) 需要 20 秒)。

以上是关于SELECT COUNT(*) with GROUP BY 对于大表来说很慢的主要内容,如果未能解决你的问题,请参考以下文章

Doctrine Query Builder Select Count with Case

如何让 mySql 返回 Select JOIN with Count?

SELECT COUNT with Group BY 仅返回值为 2

SELECT COUNT(*) with GROUP BY 对于大表来说很慢

DB2 SQL Count over Union of multiple tables with different Datatype

LINQ-Entities Group By With Range 变量查询