count(*) 和 count(列名)的区别
count(*) 和 count(列名)的区别
count 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加。最后返回累计值。
count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。
count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
id | name |
1 | 张三 |
2 | 李四 |
3 | NULL |
这里count(*)就是 3, count(`name`)就是 2。
最好不要使用count(列名)或count(常量)来替代count(*),除非统计的都是非空的记录总数。
四种 count 的区别:
既然都说到这里了,干脆就把 4 种 count 的区别都对比下:
count (字段):遍历整张表,需要取值,判断 字段!= null,按行累加;count (主键) :遍历整张表,需要取 ID,判断 id !=null,按行累加;count (1) :遍历整张表,不取值,返回的每一行放一个数字 1,按行累加;count (*):不会把全部字段取出,专门做了优化,不取值。count ( * ) 肯定不是 null(没有就是0),按行累加。count(*)和count(1) 和count(0)一样,都包括对NULL的统计
count (主键) 可能会选择最小的索引来遍历,而 count (字段) 的话,如果字段上没有索引,就只能选主键索引,所以性能上 count (字段) < count (主键)
因为 count (*) 和 count (1) 不取字段值,减少往 server 层的数据返回,所以比其他 count (字段) 要返回值的性能较好;
1.由于count(*)的算法与列偏移量无关,所以count(*)最快。
2.因为count(指定的有效值),执行计划都会转化为count(*)
3.列的偏移量决定性能,列越靠后,访问的开销越大。
如果指定的是列名,会判断是否有null,null不计算
所以结论是:
count(*) = count(1) = count(0) > count(主键 id) > count(字段)
MySQL 对 count (*) 做了什么优化?
InnoDB 是索引组织表,主键索引树的叶子节点是数据,而普通索引树的叶子节点是主键值。因此,普通索引树比主键索引树小很多。
对于 count (*) 来说,遍历哪个索引树得到的结果逻辑上都是一样的。MySQL 优化器会找到最小的那棵树来遍历。在保证逻辑正确的前提下,尽量减少扫描的数据量,是数据库系统设计的通用法则之一。
count (*) 在不同引擎中的实现方式是不一样的:
MyISAM:不支持事务,把一个表的总行数存在了磁盘上,因此执行 count (*) 的时候会直接返回这个数,效率很高;当然这里讨论的是没有 where 条件下的 count,如果有 where 条件,那么即使是 MyISAM 也必须累积计数的。InnoDB:支持事务,它执行 count (*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~