欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL优化COUNT()查询

程序员文章站 2022-03-24 13:15:54
COUNT()聚合函数,以及如何优化使用了该函数的查询,很可能是最容易被人们误解的知识点之一 ......

count()聚合函数,以及如何优化使用了该函数的查询,很可能是最容易被人们误解的知识点之一

count()的作用

count()是一个特殊的函数,有两种非常不同的作用:

  1. 统计某个列值的数量
  2. 统计行数

统计列值

在统计列值时,要求列值是非空的,即不统计null。如果在count()的括号中指定了列或者列的表达式,则统计的就是这个表达式有值的结果数。

统计结果集的行数

当mysql确认括号内的表达式的值不可能为空时,实际上就是在统计行数,最简单的就是当我们使用count(*)的时候,这种情况下通配符 * 并不会像我们猜想的那样拓展成所有的列,实际上,它会忽略所有的列而直接统计所有的行数。

因此会有一个常见的错误就是,在括号内指定了一个列却希望统计结果集的行数。如果希望知道的是结果集的行数,那么最好使用count(*)。这样写意义清晰,性能也会更好。

关于myisam的神话

一个很容易产生的误解就是:myisam的couont()函数总是非常快的,但其实这是有一个前提条件的,即只有没有任何where条件的count(*)才非常快,因为此时无需实际地计算表的行数。mysql可以利用存储引擎的特性直接获得这个值。

当统计带有where子句的结果集行数时,可以是统计某个列值的数量时,myisam的count()和其他存储引擎没有任何不同,也就不再是神话般的速度了。

简单的优化

有时候我们可以使用myisam在 count(*) 全表非常快的这个特性,来加速一些特定条件的 count() 查询。比如:

select count(*) from world.city where id > 5;

该查询查找所有id大于5的城市,这需要扫描4097行数据。但是如果我们把条件反转一下,查找id小于等于5的城市的数量,然后用总城市的数量一减就可以得到同样的结果,但是却可以把扫描的行数控制在5行以内:

select (select count(*) from world.city) - count(*)
from world.city where id <= 5;

使用近似值

有些时候并不需要完全精确的count的值,此时可以用近似值来代替。explain出来的优化器估算的行数就是一个不错的近似值,执行explain并不需要真正去执行查询,所以成本很低。