count()不同写法的区别
COUNT(字段名):返回SELECT语句检索的行中值不为NULL的行数
COUNT(1):表示的是直接查询符合条件的数据库表的行数(会包含值为NULL的行数)。其中1指的是表中的第一个字段,如有表 table(id, column1),则1指 id。
COUNT(*):表示的是直接查询符合条件的数据库表的行数(会包含值为NULL的行数),其中*
指所有所有字段,并且是SQL92定义的标准统计行数的语法,因为是标准语法,所以MySQL数据库进行过很多优化,推荐使用。
COUNT(1)和COUNT(*)区别
MySQL官方文档这么说:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
即InnoDB 对 count(1) 和 count(*) 的进行相同操作,两者性能相同。
由上述可知,可以把count(*) 和 count(1) 相同对待, 都是计算满足条件的行数(包括NULL),但count(*)是标准语法,所以推荐使用count(*)。
count() 索引使用情况
(1) count(*)、count(1)、count(主键)
如果存在二级索引则,mysql会使用二级索引计算 count(*)、count(1)、count(主键) 的值。
如果不存在二级索引则使用 主键索引(聚簇索引)计算 count(*)、count(1)、count(主键) 的值。
因为二级索引只存主键值,而没存真实数据,所以二级索引树比主键索引树更小,所以mysql优化器会选择成本更小的二级索引,不过要注意成本小,不意味着消耗时间少,这二者不是完全等同的。
具体案例分析可参考:
- 使用Count(*),count(主键),count(1)时,是走主键索引还是二级索引
- SELECT COUNT(*) 是否会造成全表扫描?
(2) count(非主键字段)
如果不存在包含该字段的索引,则会通过全表扫描来计算 count(字段)的值。
如果存在包含该字段的二级索引,则会通过扫描此二级索引 计算 count(字段) 的值。字段在索引的顺序无影响,只要索引包含该字段,即可利用该索引计算行数。
总结
(1) count(*)、count(1)、count(主键) 如果存在任何一个二级索引就会通过二级索引计算,否则使用主键索引
(2) count(非主键) 如果存在包含该字段的索引则通过索引计算,否则会使用全表扫描