[MySQL]聚集函数-count

175 阅读2分钟

在日常的开发运维中,有时候我们需要统计表中包含的总的数据行或则满足条件的数据行有多少,这个时候就会用到Aggregate Funtion中的count函数。对于统计数据库行数,多数人可能的习惯用法有count(*)、count(列名)及count(1)等,这三类用法并不完全等价,有时查询出来的结果也可能不一样。

由于mysql是一个支持多存储插件的数据库,不同的存储引擎对count实现机制也不一样。对于支持事务存储引擎innodb,不同的事务内及不同的事务隔离级别配置下,count语句返回的数据都不一样,多数情况下innodb进行count统计是需要做索引或者数据扫描的。而对于不支持事务的存储引擎MyISAM,处理不带Where条件的count时,可以直接返回全局行计数。

count(列名)

当指定列名查询时,count(列名)返回的是满足Where条件对应列不为null的行数。主键作为表中的特殊列,可以认为是不允许为null列。针对count(列)的场景,innodb都会一行一行将对应列取出来传递到server层,server层进行计数统计,而对于可以为null的列server层会增加null判断逻辑,只有不为null时才进行计数值加1,因此查询效率层面:count(主键) > count(列)。

count(*)

count(*)与count(列名)有细微的差异,count(*)返回所有的满足Where条件所有行的行数,无论其中是存在为null的列。值得注意的是,innodb中count(*)会优先使用占用空间最小的二级索引,并不会取行的数据,如果该二级索引全部都在buffer pool中,那么查询效率会比较高。

count(1)

对于innodb而言,count(*)和count(1)底层逻辑没有性能差异

参考文档

Counting Rows:https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html

function_count: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count