MySQL中count(*)和count(1)和count(column)使用比较

分页查询数据,需要返回total,而这个值一般都是通过count函数实现。但是,针对count函数,有多种写法,如count(*)、count(1) 和 count(column)等。本文主要介绍以上几种写法的差异。 注意,这里仅针对MySQL数据库,其他类型的数据库仅供参考。

count()函数简介

count() 函数是标准SQL提供的一个聚合函数,可以用来统计某个列值的数量或统计表的行数。count() 函数可以是一个表达式,该表达式可以是列名、常量、特定字符等。常见的用法有以下三种:
count(1) 用来统计表中的行数;
count(*) 用来统计表中的行数;
count(column_name) 用来统计指定列值的数目(不统计NULL值)。
需要说明的是,因为count函数的参数是表达式,所以实际用法有很多,但是最常用的还是上面三种形式。

count(*)和count(1)

count(*)和count(1)都可以用来统计表中的行数,使用上没有差异。

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

但推荐使用count(),因为这是SQL92定义的标准统计行数的语法。
在使用count(
)时,要注意不同存储引擎对其优化效果,这里主要介绍MyISAM 引擎和InnoDB 引擎对count(*)的优化。
对于 MyISAM 引擎,会把表的总行数存在了磁盘上(存放在 information_schema 库中的 PARTITIONS 表中),在不加 where 条件时,执行 count() 时会直接返回这个总数,因此效率很高,但是在加 where 限定语句的时候 MySQL 需要对全表进行检索从而得出 count 的总数。MyISAM不支持事务,使用的锁是表级锁,不会有并发的行操作,所以查询的结果是准确的。
而 InnoDB 引擎并没有像 MyISAM 那样把表的总行数存储在磁盘,而是在执行 count(
)时,在不加 where 限定语句时,MySQL Server 层需要把数据从引擎里面读出来,然后逐行累加得出总数;如果加了 where 限定语句,需要根据 where 条件从引擎里面筛选出数据,然后累加得出总数。InnoDB支持事务,并且支持行级锁,行可能被并行修改,那么缓存记录不准确。

count(column)

count(column_name) 用来统计指定列值的数目(不统计NULL值)。
如果column_name是ID等主键字段或非空字段,那么统计的结果和count(1)和count(*)的值一样。需要说明的是,对于 MyISAM 引擎,如果不加 where 条件时,直接返回的表中保存的数据总行数值;如果加 where 条件时,需要走主键索引筛选出值后再统计。对于 InnoDB 引擎,不加 where 条件时,count(id) 和 count(*) 的处理方式一样,MySQL优化器会选择最小树索引age 索引进行遍历统计;加 where 条件时,需要走主键索引筛选出值后再统计。
如果column_name是非主键字段,那么只会统计列值为NULL的行数,需要说明的是,就这种情况下,不管在 InnoDB 引擎 还是在 MyISAM引擎中,非主键这个字段如果添加了索引且覆盖该字段,则可基于索引统计行数,如果未添加索引,则会触发全表扫描。

总结

基于count()函数统计行数时,count(*)和count(1)都可以用来统计表中的行数,基于SQL规范考虑,推荐使用count(*)。注意,在使用count(*)时,要注意不同存储引擎的支持事务的水平,如MyISAM不支持事务,使用的锁是表级锁,不会有并发的行操作,所以查询的结果是准确的。InnoDB支持事务,并且支持行级锁,行可能被并行修改,那么缓存记录不准确。且不加where条件时,MyISAM 引擎会直接返回这个总数。
基于count(column_name) 统计指定列值的数目时,要注意区分主键字段和非主键字段。因为主键字段非空,所以统计的结果和count(1)和count(*)的值一样。且不加where条件时,MyISAM 引擎会直接返回这个总数。如果是非主键字段,不会统计NULL值,所以统计的结果和count(1)和count(*)的值可能不一样。且会基于该字段是否使用了索引,决定是否基于索引统计,还是全表扫描统计。

参考

https://www.runoob.com/sql/sql-func-count.html SQL COUNT() 函数
https://zhuanlan.zhihu.com/p/572387666 深度剖析:MySQL count() 函数,这下彻底明白了!
https://www.cnblogs.com/hider/p/11726690.html MySQL学习笔记:count(1)、count()、count(字段)的区别
https://zhuanlan.zhihu.com/p/28397595 高性能MySQL——Count(1) OR Count(
)?
https://zhuanlan.zhihu.com/p/391861774 SQL中的count(1)、count(*) 与 count(列名) 到底有什么区别?
高性能MySQL Baron Scbwartz, Peter Zaitsev, Vadim Tkacbenko 著, 宁海元、周振兴、彭立勋、翟卫祥 等译

你可能感兴趣的:(数据库系统概念,数据库,MySQL,count)