MySQL优化COUNT()查询
count()聚合函数,以及如何优化使用了该函数的查询,很可能是最容易被人们误解的知识点之一
count()的作用
count()是一个特殊的函数,有两种非常不同的作用:
- 统计某个列值的数量
- 统计行数
统计列值
在统计列值时,要求列值是非空的,即不统计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并不需要真正去执行查询,所以成本很低。
上一篇: MySQL数据库_数据
下一篇: 20210401雷火游戏笔试题