MySQL系列-优化之count()

1.count()函数的作用

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

我们用count(*)来统计行数,当然这个*可以是任意的常量,比如 1 'x' 666 之类的。

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()都不会通过主键索引来统计行数,在有多个二级索引的情况下选择占用空间最小的。一个优化方案就是预先建一个小字段并建二级索引专门用来统计行数,极端情况下这种优化速度提高上千倍也是正常的。—— 知乎

可以测试一下,我准备的表如下。

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

并且在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无奈的选择了主键索引。

猜你喜欢

转载自blog.csdn.net/ufo___/article/details/81178296