在面试的时候咱们会常常遇到这个问题:html
MySQL 中,COUNT(*)、COUNT(1)、COUNT(col) 有区别吗?mysql
有区别。面试
接下来咱们分析一下这三者有什么样的区别。sql
从语义角度看,它们有不一样的含义。并发
COUNT(
返回查询到的行中 expr is not-NULL 的个数,返回类型为 BIGINT(8 bytes)。expr
)
性能
Returns a count of the number of non-
NULL
values ofexpr
in the rows retrieved by aSELECT
statement. The result is aBIGINT
value.优化
COUNT(*) 有点不一样,它返回查询到的结果集中的行的个数,不论这些行是否含有 NULL 值。spa
COUNT(*)
is somewhat different in that it returns a count of the number of rows retrieved, whether or not they containNULL
values.rest
COUNT(1) 返回查询到的行中第一列 not NULL 的个数。code
COUNT(col) 返回查询到的行中 col 列中 not NULL 的个数。
在 MySQL 中讨论查询性能时,咱们须要区分存储引擎。
不一样的存储引擎以不一样的方式存储数据,这决定了最终的操做效率。
MyISAM 的主键、辅助索引都是非聚簇索引,B+树的叶节点包含的是数据的地址。
InnoDB 的主键是聚簇索引,叶节点存放的是数据自己;辅助索引是非聚簇索引,叶节点存放的是主键。
MyISAM 为每张表存储了一个准确(exact)的 row count。
所以,MyISAM 能够为 COUNT(*) 提供查询优化:当某个 SELECT 语句仅仅查询一张表、不查询其余列、没有查询条件(WHERE 子句)时,COUNT(*) 能够很快地返回这个 row count(e.g. SELECT COUNT(*) FROM tbl_name)。
当第一列定义为 NOT NULL 时,COUNT(1) 和 COUNT(*) 具备相同的查询性能。
InnoDB 是一款 transactional 存储引擎。
可能有多个事务并发操做一张表,因此 InnoDB 没法为每张表存储一个准确的 row count(由于不一样的 transaction 可能会看到不一样的 row count,row count 很难准确)。
对于 InnoDB 而言,COUNT(*)、 COUNT(1) 没有性能上的差别。
COUNT(*) 会利用索引:在 MySQL 5.7.18 以前,会利用聚簇索引;在 MySQL 5.7.18 以后,会利用一个最小的辅助索引(有的话)。