MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

Sherwin.Wei Lv7

MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

回答重点

在 MySQL 中,count(*)count(1)count(字段名) 都是用来统计行数的聚合函数,但它们有些许的区别:

功能上:

1)count(*) 会统计表中所有行的数量,包括 null 值(不会忽略任何一行数据)。由于只是计算行数,不需要对具体的列进行处理,因此性能通常较高。

2)count(1)count(*) 几乎没差别,也会统计表中所有行的数量,包括 null 值。

3)count(字段名) 会统计指定字段不为 null 的行数。这种写法会对指定的字段进行计数,只会统计字段值不为 null 的行。

效率上:

1)count(1)count(*) 效率一致,网上其实众说纷纭,实际上当然得看官网怎么说!

image.png

There is no performance difference. 没有差异的!

2)count(字段) 的查询就是全表扫描(如果对应的字段没有索引,如果有索引则用索引),正常情况下它还需要判断字段是否是 null 值,因此理论上会比 count(1)count(*) 慢。

但是如果字段不为 null,例如是主键,那么理论上也差不多,而且本质上它们的统计功能不一样,在需要统计 null 的时候,只能用 count(1)count(*),不需要统计 null 的时候只能用count(字段),所以也不用太纠结性能问题。

扩展知识

在 MyISAM 中,由于只有表锁,因此它把每张表的总数单独记录维护(表锁使得对表的修改是串行,因此能维护总数),所以 count(*) 非常快,因为等于直接返回一个字段。当然,前提是不需要条件过滤而是直接返回整表数据

而 InnoDB 由于支持行锁,所以会有很多并发来修改表的数据,因此无法维护记录总数,但是 InnoDB 对count(*)count(1)也做了一定的优化。

count 的字段如果是主键,由于主键索引保存的是整行记录,占据的空间和内存都比较大,此时表中如果还有其它二级索引,那么成本会更低,因此 InnoDB 会评估这个成本选择合适的索引扫描。当然,这个前提也是不能有对应的条件过滤等功能。

Comments
On this page
MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?