前言
平时在做业务开发时,我相信你肯定经常会遇到对数据表进行行数统计的需求,比如在查询列表的分页时,我不知道你一般是使用count(*)还是count(1)亦或是count(字段),反正我是都遇见过,他们看起来都能得到你想要的结果,不过,实际上它们还是略有不同的,本文我们就来看看这三种统计方式究竟有哪些区别。
count(expr)函数
count(expr)是一个聚合函数,在MySQL中对于它的定义是:
返回 语句检索的行中的非NULL 值数的计数。结果是一个值。 如果没有匹配的行,则 COUNT()返回 0。
-
对于count(*)来说,它有点不同,它返回的是检索到行数的记录,无论它们是否包含null值。
-
对于count(字段)来说,实际上就是判断每一行的这个字段值是否为null,如果不为null,记录才加1。
-
对于count(1)来说,很明显,它不会统计到null值,所以和count(*)统计的结果是一样的。
MyISAM和InnoDB实现方式
对于使用MyISAM作为存储引擎的表,由于引擎中直接存储了精确的行数,所以如果直接用count(*),且没有任何条件过滤,那是非常快的,而对于InnoDB这样带事务存储引擎,存储精确的行数是有问题的。多个事务可能同时发生,每个事务都可能影响计数。所以InnoDB不保留表中行的计数,SELECT COUNT(*) 语句只计算对当前事务可见的行。
所以,单从这一方面来看,不带任何条件的count(*)统计,MyISAM要比InnoDB快很多,数据量越多优势越明显。
count(*)和count(1)
经过前面的分析,我们了解到count(*)和count(1)统计出来的结果是一样的,但是对于统计的性能来说,网上有不同的说法,有的说count(*)的性能会比较差,其实并不是这样的。
关于两者的比较,官方也给出了明确的说明:InnoDB处理SELECT COUNT(*)和SELECT COUNT(1) 的方式相同。没有性能差异。
SHOW TABLE STATUS
对于InnoDB表,SHOW TABLE STATUS给出了近似的行数统计
对于MyISAM表,存储的是确切的计数。
如果对于InnoDB表只需要统计近似值,则可以使用这个方式,关于近似值与实际上的相差范围,官方给出的数据是大约在40%到50%之间