count(*)、count(1)和count(column) 深入解析
1.对于null值的统计
student表
select count(1) from student
select count(*) from student
select count(score) from student
返回结果
结论:
1.count( * )和count(1) 都是对行的数目进行计算,包含NULL值。
2.count(column) 对特定的列进行计算,不包含NULL值。
2.关于性能
看了很多文章对于三者性能的阐述脱离版本是有问题的,单就mysql5.6版本而言,三者无任何区别,都是基于查询优化器的选择。
-
1.查询对比性能
表名:ga_marketing_forecast_innodb (941859条数据)
索引状况:id:主键索引,conttt为普通索引
三次查询及执行计划如下
可以看出来性能上无任何差别,查询优化器都是选择了非主键索引,这是为什么呢? -
2.原因分析
在这里我们引入二个概念,索引基数和索引选择性。
索引基数(Cardinality)
索引基数是某索引列所包含的不同值的数量。例如,某个数据列包含值1、2、3、4、5、1,不重复的有5种,基数则为5。基数占比总数越高,索引会很快地分辨数据行。如果某列记录性别(只有0和1两值),基数为2,那么索引的用处就不大。如果值出现的几率几乎相等(男女生数量一样),那么无论搜索哪个值都可能得到一半的数据行。在这些情况下,最好根本不要使用索引,因为查询优化器发现某个值出现在表的数据行中的百分比很高的时候,它一般会忽略索引,进行全表扫描。惯用的百分比界线是”30%”
索引选择性
索引选择性=索引基数/数据总数,基数可以通过“show index from 表名”查看。
越接近1就越有可能利用索引,也可以理解1为百分百
高索引选择性的好处就是mysql查找匹配的时候可以过滤更多的行,唯一索引的选择性最佳,值为1。
那么在看一下索引的信息,这里清晰的显示conrrr索引基数小于主键,所以查询选择器的选择了非主键索引
那么现在我们强制使用主键对比非主键看看效率如何
可以清晰的看出,主键性能远低于非主键索引。