0.背景

自从大家对于MySQL数据库的稳定性有了更高的追求后,经常有小伙伴有这样的疑问,对于count(*)这样的操作,有没有正确的姿势,或者有没有可以优化的地方?

但答案比较残酷,如果已经使用了正确的索引,那么基本上没有可以优化的地方。一旦出现慢查询了,它就是慢查询了,要改,只能自己计数或者通过其他搜索平台来做。

今天,就一起来看看为什么会这样,并对大家日常会遇到的一些的困惑进行解答。

1.count(*)的实现方式

据说,MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高。

而我们的mysql一般都是用Innodb的引擎,Innodb是怎么实现count操作的呢?

InnoDB 引擎就比较麻烦来,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。

所以,当我们的表里面的记录越来越多的时候,count(*)就会越来越慢。

当然,我们这里说的都是不带where条件的,如果带上where条件的话,MyISAM也是很慢的。

2.正确的打开方式

嗯,首先还是说,mysql上不太推荐用count(*)来做统计相关业务,尤其是表非常大的情况下。

那如果业务比较小,需要快速上马,那么,至少应该保证count(*)带上了科学的where条件,然后,这个表也已经建立了科学的索引。

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

那对于统计类的业务,推荐的几种做法:

  • 带自增id的,可以用最大id来近似获取
  • 自己计数
  • 其他数据分析平台进行聚合

3.能否用表统计信息代替count(*)

有同学在日常使用过程中,问能否使用 系统表的统计信息 来代替count。

答案是不行。这里的tableRows只是一个参考值。

这里的表统计信息,实际上是使用show table status获取的。这个值是如何得到的呢?我们需要了解下mysql的采样统计方法。

为什么要采样统计呢?因为把整张表取出来一行行统计,虽然可以得到精确的结果,但是代价太高了,所以只能选择“采样统计”。(所以其实mysql自己也没有count(*)的好方法)

采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。

而数据表是会持续更新的,索引统计信息也不会固定不变。所以,当变更的数据行数超过 1/M 的时候,会自动触发重新做一次索引统计。

因此,这个采样估算得来的值,是很不准的。有多不准呢,官方文档说误差可能达到 40% 到 50%。

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知识图谱:https://github.com/saigu/JavaKnowledgeGraph (历史文章查阅非常方便)

扫码关注我的公众号“阿丸笔记”,第一时间获取最新更新。同时能免费获取海量Java技术栈电子书、各个大厂面试题哦。

聊一聊关于MySQL的count(*)的更多相关文章

  1. MySql的count统计结果

    起因:最近在学习mysql的数据库,发现在innodb表中大数据量下count(*)的统计结果实在是太慢,所以想找个办法替代这种查询,下面分享一下我查找的过程. 实践:在给出具体的结论之前,我们先看看 ...

  2. mysql函数count(*)和count(column)的区别(转)

    mysql中count(*)和count(column)使用是有区别的: count(*)对行的数目进行计算,包含NULL count(column)对特定的列的值具有的行数进行计算,不包含NULL值 ...

  3. MySQL中count函数使用方法详解

      count函数是用来统计表中或数组中记录的一个函数,下面我来介绍在MySQL中count函数用法与性能比较吧. count(*) 它返回检索行的数目, 不论其是否包含 NULL值. SELECT ...

  4. mysql Column count doesn't match value count at row 1

    今天执行批量插入的操作,发现报了错 mysql Column count doesn't match value count at row 1. 后来发现原因:是由于写的SQL语句里列的数目和后面的值 ...

  5. MySQL的COUNT()函数理解

    MySQL的COUNT()函数理解 标签(空格分隔): MySQL5.7 COUNT()函数 探讨 写在前面的话 细心的朋友会在平时工作和学习中,可以看到MySQL的COUNT()函数有多种不同的参数 ...

  6. NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用

    NET MVC全局异常处理(一)   目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...

  7. Mysql中count(*),DISTINCT的使用方法和效率研究

    在处理一个大数据量数据库的时候 突然发现mysql对于count(*)的不同处理会造成不同的结果 比如执行 SELECT count(*) FROM tablename 即使对于千万级别的数据mysq ...

  8. MySQL中Count函数的参数该传入什么样的值?

    MySQL中Count函数的参数该传入什么样的值? 查询用户表中总记录 用户表中信息如下: 1.SELECT COUNT(*) FROM USER 结果为:3条 2.  SELECT COUNT(us ...

  9. MySQL 中 count(*) 和 count(1)

    一张有 100W 条数据的表 CREATE TABLE `user` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `username` var ...

随机推荐

  1. [HDU多校]Ridiculous Netizens

    [HDU多校]Ridiculous Netizens 点分治 分成两个部分:对某一点P,连通块经过P或不经过P. 经过P采用树形依赖背包 不经过P的部分递归计算 树型依赖背包 v点必须由其父亲u点转移 ...

  2. 吴裕雄--天生自然 JAVA开发学习:文档注释

    /*** 这个类绘制一个条形图 * @author runoob * @version 1.2 */ import java.io.*; /** * 这个类演示了文档注释 * @author Ayan ...

  3. class.forName() 和 classLoader 的区别

    相同点:        java中class.forName() 和 classLoader 都可用来对类进行加载 不同店:        1.class.forName()除了将类的 .class ...

  4. CHI 2013:人机交互领域那些令人兴奋的新技术

    2013:人机交互领域那些令人兴奋的新技术" title="CHI 2013:人机交互领域那些令人兴奋的新技术"> 编者按:CHI是人机交互领域首屈一指的国际盛会, ...

  5. git相关学习地址

    https://git-scm.com/book/zh/v2    这篇文章写得不错,值得一读

  6. 吴裕雄--天生自然 HADOOP大数据分布式处理:主机与服务器时间同步设置

  7. 可用倍增LCA解题

    http://codevs.cn/problem/2370/ #include<bits/stdc++.h> using namespace std; ; ; struct node{ i ...

  8. Office Lens:口袋中的扫描仪

    Lens:口袋中的扫描仪" title="Office Lens:口袋中的扫描仪"> 编者按:开会时,你是否觉得白板上天马行空的讨论记录誊抄起来费时费事又难以共享- ...

  9. linux下使用过的命令总结(未整理完)

    1.常用命令不需解释 ls\cd\cp\mv\pwd\file\vi\vim\cat 2.getconf LONG_BIT 终端返回32表示操作系统32位,返回64表示操作系统64位. 3.ifcon ...

  10. Witness组件详解