MySQL系列-优化之count()

1.count()函数的做用

count()函数有两个做用,一是统计表数据的行数,二是统计某列非空值得数量。mysql

咱们用count(*)来统计行数,固然这个*能够是任意的常量,好比 1 'x' 666 之类的。sql

count(row)用来统计某列非空值得数量,这个row是列名。函数

2.count(1)会比count(*)快吗?

答案是不会,起码在个人mysql5.5上是这样的。性能

【当MySQL确认括号内的表达式值不可能为空时,实际上就是在统计行数。最简单的就是当咱们使用COUNT(*)的时候,这种状况下通配符*并不像咱们猜测的那样扩展成全部的列,实际上,他会忽略全部列而直接统计全部的行数 。——《高性能MySQL》】测试

因此count(*)和count(1)都同样,MySQL都会忽略因此的列。优化

3.如何加快count(*)的速度

【Innodb的主键索引是聚簇索引(包含了KEY,除了KEY以外的其余字段值,事务ID和MVCC回滚指针)因此主键索引必定会比二级索引(包含KEY和对应的主键ID)大,也就是说在有二级索引的状况下,通常COUNT()都不会经过主键索引来统计行数,在有多个二级索引的状况下选择占用空间最小的。一个优化方案就是预先建一个小字段并建二级索引专门用来统计行数,极端状况下这种优化速度提升上千倍也是正常的。—— 知乎3d

能够测试一下,我准备的表以下。指针

表的描述以下,用于统计的cnt列直接就是bit(1)了,占用空间最小,而且cnt列的值全为null。blog

而且在cnt列和name列上创建了二级索引。索引

 

执行SQL语句:explain select count(*) from tb;

能够看到,MySQL优化器用上了咱们创建的最小二级索引。

那若是把idx_cnt删掉再进行 explain select count(*) from tb; 呢?

能够试试。

和预期同样,MySQL优化器选择了name的二级索引进行统计行数。

若是再把索引idx_name删除再执行 explain select count(*) from tb;  呢?

能够看到,最后MySQL无奈的选择了主键索引。