count查询优化

  这里讨论的count查询优化是针对INNODB存储引擎的!java

  首先抛出一个问题sql

  count(*)、count(主键)、count(1)、count(字段)它们四者之间的效率如何排序?函数

  在咱们以往的工做经验中,老是听到说不要使用count(*),由于 * 号表明了全部列,计算会更慢,而后就推荐了使用count(主键)。但事实真的是这样吗?性能

笔者在最近的学习中也才认识到这个错误。学习

  这四者正确的排序应该是这样的:测试

count(1) > count(*) > count(主键) > count(字段)

  笔者特地在一张只有主键索引的1千万条数据的表中作了测试,如下是测试的结果:优化

       

 

   这张图的数据不是偶然的,笔者针对每种查询执行了屡次,结果不会有太大的变化,验证了以上排序的正确性。code

  count()的做用blog

  count()是一个特殊的函数,有两种很是不一样的做用:它能够统计某个列值的数量,也能够统计行数。在统计列值时要求列值排序

是非空的(不统计NULL)。若是在count()的括号中指定了列或者列的表达式,则统计的就是这个表达式有值的结果数,而不是NULL。

  count()的另外一个做用是统计结果集的行数。当MYSQL确认括号内的表达式值不可能为空时,实际上就是在统计行数。最简单的就

是当咱们使用count(*)的时候,这种状况下通配符 * 并不会像咱们猜测的那样扩展成全部的列,实际上,它会忽略全部的列而直接统计

全部的行数。

  最多见的一个错误就是,在括号内指定了一个列却但愿统计结果集的行数。若是但愿知道的是结果集的行数,最好使用COUNT(*),

这样写意义清晰,性能也会很好。

  count()的另外一个优化

  业务代码中,有这样一个需求,须要根据一个或多个条件,查询是否存在记录,不关心有多少条记录。广泛的SQL及代码写法以下:

SELECT count(*) FROM T WHERE a = 1 AND b = 2

  java写法以下

Integer exist = xxDao.existXxxxByXxx(params);
if ( exist != NULL ) {
  //当存在时,执行这里的代码
} else {
  //当不存在时,执行这里的代码
}

  对于此处的select count(*),并不需求将符合条件的条数都统计出来,能够优化成以下的SQL:

SELECT count(*) FROM T WHERE a = 1 AND b = 2 LIMIT 1

  这里相比上面的SQL多了LIMIT关键字,在MYSQL中,执行器执行到LIMIT关键字,只要知足LIMIT的条数,存储引擎就不会再对数据文件

进行检索,直接返回,因此这里只须要检索到1条以后就返回结果,效率可想而知快了很多!