COUNT的作用
COUNT函数在数据库可以用来统计行数,可以是表的总行数,也可以用来统计某一列的行数,或者符合条件的结果的行数。现在来看下MySQL官方文档对函数的功能描述:
Returns a count of the number of
NON-NULLvalues ofexprin the rows retrieved by aSELECTstatement. The result is aBIGINTvalue. If there are no matching rows,COUNT()returns0.COUNT(DISTINCT exp): Returns a count of the number of rows with different non-NULLexprvalues.
注意:使用COUNT([DISTINCT] expr)统计expr时,统计的是non-null的行数。
以下是COUNT函数的具体使用:
1 | -- 统计表的总行数 |
COUNT(1) VS COUNT(*)
COUNT(1)与COUNT(*)在功能上一样,都是用来统计行数。但这里要讨论的区别,主要是指数据库性能上的差异。有些人可能会觉得,COUNT(1)会比COUNT(*)性能更好一些。但是,根据MySQL官方文档的解释,在Innodb存储引擎中,其实二者并没有性能上的差异[1]。以下是MySQL官方解释:
InnoDBhandlesSELECT COUNT(*)andSELECT COUNT(1)operations in the same way. There is no performance difference.
COUNT函数与存储引擎
对于Innodb存储引擎,执行COUNT(*)统计行数,需要对表一行一行的计数统计。但对于采用了MyISAM存储引擎的表,COUNT(*)的速度非常快,这是因为MySQL可以利用MyISAM的存储引擎特性(MyISAM 引擎把一个表的总行数存在了磁盘上)直接获得这个值,但这也只适用于没有WHERE条件的COUNT(*),即SELECT COUNT(*) FROM t,MyISAM在处理使用了过滤条件的统计或统计部分列,其实速度与别的存储引擎并没有什么不同[1]。
For
MyISAMtables,COUNT(*)is optimized to return very quickly if theSELECTretrievesFROMone table, no other columns are retrieved, and there is noWHEREclause.
如何从事务的角度分析
InnoDB的COUNT(?)?由于
InnoDB引擎支持事务的特性,数据表中的一行记录,可能有多个版本 (row),每个版本有自己的 row trx_id。所以,对于InnoDB引擎来说,不同事务中count(?)的结果可能是不一致的。
总结
使用了MyISAM 引擎的表, COUNT(*) 速度很快,但是MyISAM引擎不支持事务,而且含有 where 条件 COUNT与别的引擎没什么不同。show table status 命令虽然返回很快,但是结果不够准确[2]。
对使用了InnoDB 引擎的表直接 COUNT(*) 的结果很准确,但会遍历全表,这可能会导致性能问题。
效率对比:count(*)~count(1)>count(column_x)
参考文档
[1] MySQL 8.0 Reference Manual: Aggregate Function Descriptions - count