我的编程空间,编程开发者的网络收藏夹
学习永远不晚

聊一聊关于MySQL的count(*)

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

聊一聊关于MySQL的count(*)

聊一聊关于MySQL的count(*)

2. count(*)的实现方式

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

3.正确的打开方式

嗯,首先还是说,mysql上不太推荐用count(*)来做统计相关业务,尤其是表非常大的情况下。 那如果业务比较小,需要快速上马,那么,至少应该保证count(*)带上了科学的where条件,然后,这个表也已经建立了科学的索引。

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

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

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

4. 能否用表统计信息代替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(字段)

看到这里了,原创不易,点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

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

阿丸笔记

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

聊一聊关于MySQL的count(*)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

聊一聊关于MySQL的count(*)

2. count(*)的实现方式据说,MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高。而我们的mysql一般都是用Innodb的引擎,Innodb是怎么实现count操作的呢?InnoDB 引擎就比
聊一聊关于MySQL的count(*)
2020-12-23

聊聊MySQL的COUNT(*)的性能

前言 基本职场上的程序员用来统计数据库表的行数都会使用count(*),count(1)或者count(主键),那么它们之间的区别和性能你又是否了解呢? 其实程序员在开发的过程中,在一张大表上统计总行数是非常耗时的一个操作,那么我们应该用哪
2022-05-25

聊一聊关于php源码中refcount的疑问

这篇文章主要给大家介绍了关于对php源码中refcount的相关疑问,文中通过实例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友可以参考下
2022-11-13

聊聊Python中关于a=[[]]*3的反思

Python 关于a=[[]]*3的反思 之前用python做了一个关于交通大数据的项目,由于之前比较赶进度,故现在会陆续更新对项目代码的一些反思。 1、由此可以看出,a[0],a[1],a[2]指向的是同一个元素,[[]]*3表示在a中开
2022-06-02

聊一聊Android中的StateListAnimator

简评:使用 StateListAnimator 轻松实现 Material Design 效果。Material Design 中最基础的一条原则就是 'motion provides meaning',也就是当用户和你的 app 交互时应
2022-06-06

聊聊MySQL中的参数

前言: 在前面一些文章中,经常能看到介绍某某参数的作用,可能有些小伙伴仍搞不清楚 MySQL 参数是啥。本篇文章我们来聊聊 MySQL 参数,学习下如何管理维护 MySQL 参数。 1.MySQL参数概念 我们所说的参数在官方文档中称为 系
2022-05-29

一文聊聊Node中的stream(流)

什么是流?如何理解流?下面本篇文章就来带大家深入了解一下Nodejs中的流(Stream),希望对大家有所帮助!
2023-05-14

带你聊聊typeScript中的extends关键字

extends 是 typeScript 中的关键字。在 typeScript 的类型编程世界里面,它所扮演的角色实在是太重要了,所以,我们不得不需要重视它,深入学习它。
2023-05-14

聊聊MySQL中的存储引擎

基础知识在关系型数据库中每一个数据表相当于一个文件,而不同的存储引擎则会构建出不同的表类型。存储引擎的作用是规定数据表如何存储数据,如何为存储的数据建立索引以及如何支持更新、查询等技术的实现。在Oracle以及SqlServer等数据库中只
2022-05-23

一文聊聊vue3中的ref、toRef、toRefs

本篇文章带大家深入聊聊vue3项目中关于ref、toRef、toRefs的使用方法,希望对大家有所帮助!
2023-05-14

编程热搜

目录