1、COUNT有几种用法?
2、COUNT(字段名)和COUNT(*)的查询结果有什么不同?
3、COUNT(1)和COUNT(*)之间有什么不同?
4、COUNT(1)和COUNT(*)之间的效率哪个更高?
5、为什么《阿里巴巴Java开发手册》建议使用COUNT(*)
6、MySQL的MyISAM引擎对COUNT(*)做了哪些优化?
7、MySQL的InnoDB引擎对COUNT(*)做了哪些优化?
8、上面提到的MySQL对COUNT(*)做的优化,有一个关键的前提是什么?
9、SELECT COUNT(*) 的时候,加不加where条件有差别吗?
10、COUNT(*)、COUNT(1)和COUNT(字段名)的执行过程是怎样的?
COUNT(*)
的统计结果中,会包含值为NULL的行数。insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)
from #bla
results 7 3 2
COUNT(id)
和COUNT(*)
以外,还可以使用COUNT(常量)
(如COUNT(1)
)来统计行数,那么这三条SQL语句有什么区别呢?到底哪种效率更高呢?为什么《阿里巴巴Java开发手册》中强制要求不让使用 COUNT(列名)
或 COUNT(常量)
来替代 COUNT(*)
呢?COUNT(列名)、COUNT(常量)和COUNT(*)之间的区别
COUNT(expr)
用于做行数统计,统计的是expr不为NULL的行数,那么COUNT(列名)
、 COUNT(常量)
和 COUNT(*)
这三种语法中,expr分别是列名
、 常量
和 *
。列名
、 常量
和 *
这三个条件中,常量
是一个固定值,肯定不为NULL。*
可以理解为查询整行,所以肯定也不为NULL,那么就只有列名
的查询结果有可能是NULL了。COUNT(常量)
和 COUNT(*)
表示的是直接查询符合条件的数据库表的行数。而COUNT(列名)
表示的是查询符合条件的列的值不为NULL的行数。COUNT(*)
相比COUNT(常量)
和 COUNT(列名)
来讲,COUNT(*)是SQL92定义的标准统计行数的语法,因为他是标准语法,所以MySQL数据库对他进行过很多优化。COUNT(*)的优化
COUNT(*)
是SQL92定义的标准统计行数的语法,所以MySQL数据库对他进行过很多优化。那么,具体都做过哪些事情呢?COUNT(*)
有关,那就是MyISAM不支持事务,MyISAM中的锁是表级锁;而InnoDB支持事务,并且支持行级锁。SELECT COUNT(*) FROM tbl_name
语句,确实在扫表的过程中做了一些优化。前提是查询语句中不包含WHERE或GROUP BY等条件。COUNT(*)和COUNT(1)
COUNT(*)
,接下来看看COUNT(1)
,对于,这二者到底有没有区别,网上的说法众说纷纭。COUNT(*)
执行时会转换成COUNT(1)
,所以COUNT(1)少了转换步骤,所以更快。COUNT(*)
做了特殊优化,所以COUNT(*)
更快。InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
same way
, no performance difference
。所以,对于COUNT(1)和COUNT(*),MySQL的优化是完全一样的,根本不存在谁比谁快!COUNT(*)
和COUNT(1)
一样,建议用哪个呢?COUNT(*)
!因为这个是SQL92定义的标准统计行数的语法,而且本文只是基于MySQL做了分析,关于Oracle中的这个问题,也是众说纷纭的呢。COUNT(字段)
COUNT(*)
,COUNT(字段)
多了一个步骤就是判断所查询的字段是否为NULL,所以他的性能要比COUNT(*)
慢。总结
COUNT(*)
、COUNT(字段)
和COUNT(1)
。COUNT(*)
是SQL92定义的标准统计行数的语法,所以MySQL对他进行了很多优化,MyISAM中会直接把表的总行数单独记录下来供COUNT(*)
查询,而InnoDB则会在扫表的时候选择最小的索引来降低成本。当然,这些优化的前提都是没有进行where和group的条件查询。COUNT(*)
和COUNT(1)
实现上没有区别,而且效率一样,但是COUNT(字段)
需要进行字段的非NULL判断,所以效率会低一些。COUNT(*)
是SQL92定义的标准统计行数的语法,并且效率高,所以请直接使用COUNT(*)
查询表的行数!参考资料:
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count
《极客时间——MySQL实战45讲》
推荐阅读
公众号@陈树义,用最简单的语言,分享我的技术见解。