count(1)、count(*)、count(column)

有where条件的count,会根据扫码结果count一下所有的行数,其性能更依赖于where条件,所以仅仅针对没有where的情况进行说明;

Myisam会把一个表的总行数记录下来,在执行count(*)时直接返回数量执行效率很高。
InnoDB 因为增加了版本控制(MVCC)的原因,同时有多个事务访问数据并且有更新操作的时候,每个事务需要维护自己的可见性,那么每个事务查询到的行数也是不同的,所以不能缓存具体的行数,他每次都需要 count 一下所有的行数。

在InnoDB下,COUNT(1)和COUNT(*)哪个快呢?
结论是:这俩在高版本的MySQL(5.5及以后,5.1的没有考证)是没有什么区别的,也就没有COUN(1)会比COUNT(*)更快这一说了。
WHY?这就要从COUNT()函数的具体含义说起了.

COUNT()有两个非常不同的作用:它可以统计某个列值的数量,也可以统计行数。在统计列值时要求列值是非空的(不统计NULL)。如果在COUNT()的括号中定了列或者列表达式,则统计的就是这个表达式有值的结果数。…COUNT()的另一个作用是统计结果集的行数。当MySQL确认括号内的表达式值不可能为空时,实际上就是在统计行数。最简单的就是当我们使用COUNT()的时候,这种情况下通配符并不像我们猜想的那样扩展成所有的列,实际上,他会忽略所有列而直接统计所有的行数

通常,我们将第一个字段(一般是ID)作为主键,那么这个时候COUNT(1)实际统计的就是行数,因为主键肯定是非NULL的。问题是Innodb是通过主键索引来统计行数的吗?结论是:如果该表只有一个主键索引,没有任何二级索引的情况下,那么COUNT(*)和COUNT(1)都是通过通过主键索引来统计行数的。如果该表有二级索引,则COUNT(1)和COUNT()*都会通过占用空间最小的字段的二级索引进行统计,也就是说虽然COUNT(1)指定了第一列(此处表达有误,详见文章结尾)但是innodb不会真的去统计主键索引(一般为第一个字段的索引)。

count(column) 也是会遍历整张表,但是不同的是它会拿到 column 的值以后判断是否为空,然后再进行累加,那么如果针对主键需要解析内容,如果是二级所以需要再次根据主键获取内容,又是一次 IO 操作,所以 count(column) 的性能肯定不如前两者喽,如果按照效率比较的话:count(*)=count(1)>count(primary key)>count(column)

参考自:
https://zhuanlan.zhihu.com/p/28397595
https://www.zhihu.com/follow

猜你喜欢

转载自blog.csdn.net/qq_37935909/article/details/108639717