SELECT COUNT(*) FROM table_name
是个再常见不过的统计需求了。
本文带你了解下Mysql
的COUNT
函数。php
COUNT
函数关于COUNT
函数,在MySQL
官网中有详细介绍:html
翻译一下:mysql
COUNT(expr)
,返回SELECT
语句检索的行中expr
的值不为NULL
的数量,结果是一个BIGINT
值。0
COUNT(*)
的统计结果中,会包含值为NULL
的行数。在《阿里巴巴Java开发手册》也有以下要求:git
COUNT(列名)
、COUNT(常量)
和COUNT(*)
前面咱们提到过
COUNT(expr)
用于作行数统计,那么COUNT(列名)
、COUNT(常量)
和COUNT(*)
这三种语法中,expr
分别是列名、 常量 和*
。github
COUNT(*)
和COUNT(常量)
在列名、常量和*
这三个条件中,常量是一个固定值,确定不为NULL
。*
能够理解为查询整行,因此确定也不为NULL
,那么就只有列名的查询结果多是NULL
。sql
因此, COUNT(常量)
和 COUNT(*)
表示的是直接查询符合条件的数据库表的行数。而COUNT(列名)
表示的是查询符合条件的列的值不为NULL
的行数。数据库
COUNT(*)
和COUNT(1)
区别COUNT(1)
就是COUNT(常量)
,对于这两者到底有没有区别:缓存
COUNT(*)
执行时会转换成COUNT(1)
,因此COUNT(1)
少了转换步骤,因此更快。MySQL
针对COUNT(*)
作了特殊优化,因此COUNT(*)
更快。到底哪一种说法是对的?看下MySQL
官方文档:函数
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
经过文档,对于COUNT(1)
和COUNT(*)
,MySQL
的优化是彻底同样的,根本不存在谁比谁快!post
COUNT(列名)
相较于前二者,COUNT(列名)
的查询就比较简单粗暴了,就是进行全表扫描,而后判断指定字段的值是否是为NULL
,不为NULL
则累加。
相比
COUNT(*)
,COUNT(列名)
多了一个步骤就是判断所查询的字段是否为NULL
,因此他的性能要比COUNT(*)
慢。
here和group的条件查询。
SQL92
除了查询获得结果集有区别以外,COUNT(*)
相比COUNT(常量)
和 COUNT(列名)
来说,COUNT(*)
是SQL92
定义的标准统计行数的语法,由于他是标准语法,因此MySQL
数据库对他进行过不少优化。
SQL92
,是数据库的一个ANSI/ISO
标准。它定义了一种语言(SQL
)以及数据库的行为(事务、隔离级别等)。
COUNT(*)
优化由于COUNT(*)
是SQL92
定义的标准统计行数的语法,因此MySQ
L对其进行了不少优化:
MyISAM
中会直接把表的总行数单独记录下来供COUNT(*)
查询InnoDB
会在扫表的时候选择最小的索引来下降成本。这些优化的前提都是没有进行
where
和group
的条件查询,更多请参考MySQL 全表 COUNT(*) 简述
COUNT
函数用于统计表行数,按照效率比较的话:
count(*)=count(常量)>count(列名)
既然 count(*)
在查询上依赖于全部的数据集,因此咱们在设计上也须要尽可能的规避全量 count
。
一般状况咱们针对可预见的 count
查询会作适当的缓存,能够是 Redis
,也能够是独立的 MySQL
count
表。