聊一聊关于MySQL的count(*)

坚持更新Java技术栈相关总结,Java、MySQL、各类中间件等,关注公众号【阿丸笔记】获取第一时间更新。
收集技术相关电子书、面试题,有须要的小伙伴能够关注公众号【阿丸笔记】,无套路领取。mysql

1. 背景

自从你们对于MySQL数据库的稳定性有了更高的追求后,常常有小伙伴有这样的疑问,对于count(*)这样的操做,有没有正确的姿式,或者有没有能够优化的地方?
但答案比较残酷,若是已经使用了正确的索引,那么基本上没有能够优化的地方。
一旦出现慢查询了,它就是慢查询了,要改,只能本身计数或者经过其余搜索平台来作。
今天,就一块儿来看看为何会这样,并对你们平常会遇到的一些的困惑进行解答。web

2. count(*)的实现方式

听说,MyISAM 引擎把一个表的总行数存在了磁盘上,所以执行 count(*) 的时候会直接返回这个数,效率很高。
而咱们的mysql通常都是用Innodb的引擎,Innodb是怎么实现count操做的呢?
InnoDB 引擎就比较麻烦了,它执行 count(*) 的时候,须要把数据一行一行地从引擎里面读出来,而后累积计数。
因此,当咱们的表里面的记录愈来愈多的时候,count(*)就会愈来愈慢。
固然,咱们这里说的都是不带where条件的,若是带上where条件的话,MyISAM也是很慢的。面试

3.正确的打开方式

嗯,首先仍是说,mysql上不太推荐用count(*)来作统计相关业务,尤为是表很是大的状况下。
那若是业务比较小,须要快速上马,那么,至少应该保证count(*)带上了科学的where条件,而后,这个表也已经创建了科学的索引。sql

  • 若是count(*)带上的where条件,并且可以走覆盖索引,那仍是能够偶尔走一走的。
  • 若是count(*)带上的where条件,可以走索引,可是须要回表,那么这种就会比较危险,尤为是随着表规模的扩大,终究是一颗雷。
  • 若是纯粹count(*),或者where条件没有任何索引,万万万不推荐!

那对于统计类的业务,推荐的几种作法:数据库

  • 带自增id的,能够用最大id来近似获取
  • 本身计数
  • 其余数据分析平台进行聚合

4. 可否用表统计信息代替count(*)

有同窗在平常使用过程当中,问可否使用 系统表的统计信息 来代替count。
答案是不行。
这里的tableRows只是一个参考值。
这里的表统计信息,其实是使用show table status获取的。这个值是如何获得的呢?咱们须要了解下mysql的采样统计方法。为何要采样统计呢?
由于把整张表取出来一行行统计,虽然能够获得精确的结果,可是代价过高了,因此只能选择“采样统计”(因此其实mysql本身也没有count(*)的好方法)。
采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不一样值,获得一个平均值,而后乘以这个索引的页面数,就获得了这个索引的基数。而数据表是会持续更新的,索引统计信息也不会固定不变。
因此,当变动的数据行数超过 1/M 的时候,会自动触发从新作一次索引统计。
所以,这个采样估算得来的值,是很不许的。有多不许呢,官方文档说偏差可能达到 40% 到 50%。svg

4.关于那些奇奇怪怪的count(?)

在看一些老代码查询的时候,咱们常常会看到count(1),count(id),count(字段)等方式,那它们纠结孰优孰劣,到底有没有性能上的差别呢?
这里,咱们先要弄清楚 count() 的语义。
count() 是一个聚合函数,对于返回的结果集,一行行地判断,若是 count 函数的参数不是 NULL,累计值就加 1,不然不加。最后返回累计值。函数

  • count(主键id)InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加
  • count(1)InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
  • count(字段)若是这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;若是这个“字段”定义容许为 null,那么执行的时候,判断到有多是 null,还要把值取出来再判断一下,不是 null 才累加。
  • count(*)并不会把所有字段取出来,而是专门作了优化,不取值。count(*) 确定不是 null,按行累加。

因此结论是:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),因此我建议,尽可能使用 count(*)。性能

扫码关注个人公众号“阿丸笔记”,第一时间获取最新更新。
无套路获取Java技术栈电子书、各个大厂面试题。
阿丸笔记优化