1、 count()的作用
计数函数,既可以统计某个列的数量又可以统计行数。
统计列Count(col_name),只统计非NULL列( 在 统 计 列 值 时 ( c o u n t ( c o l ) ) , 列 应 该 是 非 空 的 ( N U L L 列 不 会 计 数 );如果列为非空会优化器会将Count(col_name)转换为Count(*) )
统计行Count(*),统计结果集的行数。
2、 * 会检查所有的列?
不是的,当我们使用count(*)的时候,通配符*不会检查所有的列,而是直接统计所有的行数;count(col),当col为非空列时,会转换成count(*)。
3、 count() innodb与myisam对比
我们现在有两张表class_video和class_video_isam, class_video表存储引擎为innodb,class_video_isam存储引擎为myisam。
class_video:
class_video_isam:
在数据量都是3162560(300百万)条的场景,执行一下 select count(*) from class_video 和 select count(*) from class_video_isam:
myisam存储引擎0.001s,innodb存储引擎:23.381s
差别这么大,什么原因?
myisam存储引擎为了存储了这张表的总行数,而innodb需要逐行计数。但是myisam的这么快是有前提:即没有where子句,比如:select count(*) from class_video_isam where course_id=1540;
执行时间33.522秒。
4、 如何优化?
4.1 innodb count(*) 无where条件:
- 增加统计表或者使用缓存。
4.2 有where条件:
- 分析业务,减少扫描行数。
- 可以根据该条件建立条件统计表。
- 如果业务可以接受,那么使用近似行,近似行采用EXPLAIN语句,优化器会预估一个行数。
使用缓存。
5、 总结
- 行数统计使用Count(*),统计列使用Count(col_name),如果col_name定义为非NULL,那么优化器会自动将Count(col_name)转换为Count(*)。
- MyISAM和InnoDB计数略有不同,MyISAM直接存储了行数,所有全表行数统计非常快,而InnoDB需要扫描整张表。
- 优化Count()主要是减少结果集扫描行数,比如:总是使用小的结果集;使用近似值(避免扫描);使用缓存;定时更新;汇总表。
- 优化Count()还可以组合以上的方式,比如:定时更新,将汇总更新到汇总表,然后将汇总表内容写入缓存。
6、 参考
- 高性能MySQL(第三版)