count(*): 对行的数目进行计算,包含NULL。
count(1): 将对应的行记作1,累加1得出总行数,包含NULL。
count(column_name): 对特定的列的值具有的行数进行计算,不包含NULL值。
1、当没有where条件且表中有主键且表中只有主键索引的情况下,经过总数据量为6498854的测试得出以下结论
效率:count(*) ≈ count(1) ≈ count(id) > count(column_name)
select count(*) from t_user; -- 执行三次,平均:1.002s
select count(1) from t_user; -- 执行三次,平均:0.982s
select count(name) from t_user; -- 执行三次,平均:2.097s
select count(id) from t_user; -- 执行三次,平均:0.980s
2、当没有where条件且表中有主键且表中有普通索引name的情况下,其实和第一点的差别并不大,能看到加了name索引的情况比没有加name索引的情况效率还要低,是因为count()并不需要根据索引去进行汇总,但是又维护多了一个索引表,所以速度稍微慢些,除非有where条件去过滤name的值,即使这样速度还是会比其他三个慢
效率:count(*) ≈ count(1) ≈ count(id) > count(column_name)
select count(*) from t_user; -- 执行三次,平均:0.979s
select count(1) from t_user; -- 执行三次,平均:0.983s
select count(name) from t_user; -- 执行三次,平均:2.130s
select count(id) from t_user; -- 执行三次,平均:0.976s
3、当有where条件且表中有主键且表中只有主键索引时,其实各个的时间都变慢了,只不过count(column_name)的速度还是最慢的
select count(*) from t_user where age > 10; -- 执行三次,平均:2.116s
select count(1) from t_user where age > 10; -- 执行三次,平均:2.151s
select count(name) from t_user where age > 10; -- 执行三次,平均:2.389s
select count(id) from t_user where age > 10; -- 执行三次,平均:2.348s
得出结论:
1、从以上可以看出,平均下来count(*)的效率都是相对较好的,所以优先选择使用count(*),因为count(*)是SQL92定义的标准统计行数的语法,因为他是标准语法,所以MySQL数据库对他进行过很多优化。[alibaba开发手册崇山版]
在INNODB与MYISAM中统计当前数据行,用count(*)有什么区别?
1、MyISAM对于表的行数做了优化,具体做法是有一个变量存储了表的行数,如果查询条件没有WHERE条件则是查询表中一共有多少条数据,MyISAM可以做到迅速返回,前提条件是没有where语句的哦
2、InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。那么为什么InnoDB没有了这个变量呢?因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。 如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。