Count(1)、Count(列名) 与 Count(*) 区别

结论:

    官方建议使用count(*),是SQL92 定义的标准统计行数的语法​,数据库进行了优化。
    COUNT(1)和COUNT( * )执行优化器的优化是完全一样的,并没有COUNT(1)会比COUNT(*)快。
    COUNT(1) 和 COUNT( * )表示的是直接查询符合条件的数据库表的行数。
    而COUNT(列名)表示的是查询符合条件的列的值不为NULL的行数。

解释:
COUNT()有两个非常不同的作用:
 一.统计某个列值的数量,在统计列值时要求列值是非空的(不统计NULL)。如果在COUNT()的括号中定了列或者列表达式,则统计的就是这个表达式有值的结果数。
 二.统计行数。当MySQL确认括号内的表达式值不可能为空时,实际上就是在统计行数。最简单的就是当我们使用COUNT(*)的时候,这种情况下通配符*并不像我们猜想的那样扩展成所有的列,
 实际上,他会忽略所有列而直接统计所有的行数.
                                                                ——《高性能MySQL》。
统计行数

MyISAM
    MyISAM对于表的行数做了优化,用一个变量存储了表的行数,前提是不能加有任何WHERE条件。
    MyISAM之所以可以把表中的总行数记录下来供COUNT(*)查询使用,那是因为MyISAM数据库是表级锁,不会有并发的数据库行数修改,所以查询得到的行数是准确的。
    对于InnoDB来说,就不能做这种缓存操作了,因为InnoDB支持事务,其中大部分操作都是行级锁,所以可能表的行数可能会被并发修改,那么缓存记录下来的总行数就不准确了。

InnoDB
    对COUNT(*)优化:使用COUNT( * )查询行数时,在查询语句中不包含WHERE或GROUP BY等条件下,通过提高全表扫描效率来实现,MySQL会优先选择最小的非聚簇索引来扫表(如果存在)。
    磁盘的数据库的性能瓶颈主要都是在IO阶段,相比于CPU和RAM,IO操作实在太慢了,所以需要尽可能减少IO的次数。这里统计行数的操作,查询优化器的优化方向就是选择能够让IO次数最少的索引,也就是基于占用空间最小的字段所建的索引(每次IO读取的数据量是固定的,索引占用的空间越小所需的IO次数也就越少)。而Innodb的主键索引是聚簇索引(包含了KEY,除了KEY之外的其他字段值,事务ID和MVCC回滚指针)所以主键索引一定会比二级索引(包含KEY和对应的主键ID)大,也就是说在有二级索引的情况下,一般COUNT()都不会通过主键索引来统计行数,在有多个二级索引的情况下选择占用空间最小的。

参考
    阿里云开发者社区
结尾

​ 有不足之处欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值