2. count(*)的实现方式 据说,MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高。 而我们的Mysql一般都是用Innodb的引擎,Innodb是怎么实现count操作的呢
据说,MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高。 而我们的Mysql一般都是用Innodb的引擎,Innodb是怎么实现count操作的呢? InnoDB 引擎就比较麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。 所以,当我们的表里面的记录越来越多的时候,count(*)就会越来越慢。 当然,我们这里说的都是不带where条件的,如果带上where条件的话,MyISAM也是很慢的。
嗯,首先还是说,mysql上不太推荐用count(*)来做统计相关业务,尤其是表非常大的情况下。 那如果业务比较小,需要快速上马,那么,至少应该保证count(*)带上了科学的where条件,然后,这个表也已经建立了科学的索引。
那对于统计类的业务,推荐的几种做法:
有同学在日常使用过程中,问能否使用 系统表的统计信息 来代替count。 答案是不行。 这里的tableRows只是一个参考值。 这里的表统计信息,实际上是使用show table status获取的。这个值是如何得到的呢?我们需要了解下mysql的采样统计方法。为什么要采样统计呢? 因为把整张表取出来一行行统计,虽然可以得到精确的结果,但是代价太高了,所以只能选择“采样统计”(所以其实mysql自己也没有count(*)的好方法)。 采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。而数据表是会持续更新的,索引统计信息也不会固定不变。 所以,当变更的数据行数超过 1/M 的时候,会自动触发重新做一次索引统计。 因此,这个采样估算得来的值,是很不准的。有多不准呢,官方文档说误差可能达到 40% 到 50%。
在看一些老代码查询的时候,我们经常会看到count(1),count(id),count(字段)等方式,那它们纠结孰优孰劣,到底有没有性能上的差异呢? 这里,我们先要弄清楚 count() 的语义。 count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加。最后返回累计值。
所以结论是:按照效率排序的话,count(字段)
看到这里了,原创不易,点个赞吧,你最好看了~
知识碎片重新梳理,构建Java知识图谱:https://GitHub.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)
--结束END--
本文标题: 聊一聊关于MySQL的count(*)
本文链接: https://lsjlt.com/news/4720.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-10-23
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0