- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅谈MySQL 统计行数的 count由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
MySQL count() 函数我们并不陌生,用来统计每张表的行数。但如果你的表越来越大,且是 InnoDB 引擎的话,会发现计算的速度会越来越慢。在这篇文章里,会先介绍 count() 实现的原理及原因,然后是 count 不同用法的性能分析,最后给出需要频繁改变并需要统计表行数的解决方案.
Count() 的实现 。
InnoDB 和 MyISAM 是 MySQL 常用的数据引擎,由于两者实现的不同,导致 count() 操作计算的效率也不同.
对于 MyISAM 来说,它把每个表的总行数都存在了磁盘上,因此使用 count(*) 计算时,效率很高直接返回结果。但如果加入了 where 条件,依然会进行搜索,所以效率是不高的.
对于 InnoDB 来说,在进行 count(*) 运算时,会把数据从引擎中一行行读出来,然后累计计数,自然表大了之后,效率就变低了.
那么,为什么 InnoDB 不能像 MyISAM 在表中记录呢?原因就在于 InnoDB 比 MyISAM 多了支持事务的特性,同时也需要一定的取舍。由于 MVCC 的控制,使得 MySQL 具有并发的能力,也就是说对于同一时刻,InnoDB 返回的表的行数是不一定的,事务看到的行数与开启后的一致性视图有关,换句话说,每个事务能看到的数据版本是不一样的,只能一行行拿出来进行判断.
像下面的事务,假设表 t 有 10000 条数据:
Session A | Session B | Session C |
select count(*) from t; | ||
insert into t (); | ||
begin; | ||
insert into t(); | ||
select count(*) from t; | select count(*) from t; | select count(*) from t; |
10000; | 结果是 10002 | 结果是 10001 |
对于 Session A 来说,Session B 未提交不可见,Session C 提交了,但是在 Session A 启动后提交的,也不可见。所以是 10000. 。
而对于 Session B 而言,Session C 在启动之前提交,自己又插入了一条,所以结果是 10002. 。
其实 InnoDB 在进行 count(*) 操作时,还是做了优化的,在进行 count(*) 操作时,由于普通索引会保存主键的 id 值,所以会找到最小的那颗普通索引树进行查找,而不是去遍历主键索引树.
在保证逻辑正确的前提下,减少扫描的数据量,是数据库系统设计的通用法则.
另外在使用 show table status 时,也可以查询出行数,而且速度很快,但需要注意的是,该命令是通过索引统计的值来采样估算的。官方文档说误差可以有 40%-50%. 。
但如果我们真的需要实时的获取的某个表的行数,应该怎么办呢?
手动保存表的数量 。
用缓存系统来保存计数 。
对于进行更新的表,可能会想到用缓存系统来支持。比如 Redis 里来保存某个表总行数.
每次插入数据库时,Redis 计数加一,相反则减一,这样看起来读写操作都很快,但会存在一些问题.
缓存系统会丢失更新:
对于 Redis 在内存中的数据,需要定期的同步到磁盘中,但对于 Redis 异常重启,就没有办法了。比如在 Redis 中插入后,Redis 重启,数据没有持久化到硬盘。这时可以在重启 Redis 后,从数据库执行下 count(*) 操作,然后更新到 Redis 中。一次全表扫描还是可行的.
逻辑不精确:
假设一个页面中,需要显示一张表的行数,以及每一条数据。在实现时,可以先从 Redis 取数量,然后从数据库里取记录.
但可能会出现这样的情况:
Session A | Session B | |
插入一条数据; | T1 | |
读 Redis 计数; | T2 | |
从数据库中查记录; | ||
Redis 计数加 1; | T3 |
对于 Session B 来说,在 T2 时刻,会发现 Redis 的数量比数据库少 1 条.
。
Session A | Session B | |
Redis 计数加 1; | T1 | |
读 Redis 计数; | T2 | |
从数据库中查记录; | ||
插入一条数据; | T3 |
。
对于 Session B 来说,在 T2 时刻,会发现 Redis 的数量比数据库多 1 条.
其实产生问题的原因就是因为 Redis 和数据库查记录没有在同一个事务中.
用数据库保存 。
由于 InnoDB 引擎的支持,MySQL 本身是支持事务的,所以将 Redis 的插入操作换成在数据库的更新操作,就可以利用在RR级别下的事务特性,进而保证数据的精确性.
而且还有一点,由于 redo log 的支持,在 MySQL 发生异常时,是可以保证 crash-safe.
不同 count 用法的执行效率 。
count() 本身是一个聚合函数,对于返回的结果集,一行行地判断。如果参数不是 NULL 的话,会一直累加,最后返回结果.
所以 count(*), count(id), count(1) 表示都是返回满足条件的结果集总行数.
而 count(字段),则表示满足条件的数据行里,不为 NULL 的字段.
对于 count(id) 来说,InnoDB 会遍历整张表,把每行 id 取出来,给 server 层。Server 判断 id 是否为空,然后累加.
对于 count(1) 来说,InnoDB 会遍历整张表,但不取值。Server 层会自己放入 1,然后累加.
所以对于 count(1) 的执行会比 count(*) 要快,少了解析数据行以及拷贝字段值的操作.
对于 count(字段) 来说,如果字段定义时是 not null, 会一行行读出,并判断不能为 null,然后累加。如果定义时可以为 null,执行时,需要将值去除,判断不是 null 才累加.
count(*) 除外,专门做了优化,不取值,直接按行累加,并且会找到最小的索引树进行计算.
总结 。
MySQL count() 函数的执行效率和底层的数据引擎有关。MyISAM 不加 where 条件,查询会很快,但不支持事务。InnoDB 支持事务,由于 MVCC 的实现,导致每次查询都需要一行行的扫描,效率不高.
解决方法可以通过设计外部缓存如 Redis,保存记录。但存在异常重启和数据不准确的情况。可以通过在 InnoDB 中新建一张表,保存记录这样的解决方案.
最后,InnoDB 对 count(*) 做了独立的优化,而其他的 count 操作,则需要额外的操作.
以上就是浅谈MySQL 统计行数的 count的详细内容,更多关于Mysql count的资料请关注我其它相关文章! 。
原文链接:https://www.cnblogs.com/michael9/p/12513327.html 。
最后此篇关于浅谈MySQL 统计行数的 count的文章就讲到这里了,如果你想了解更多关于浅谈MySQL 统计行数的 count的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我目前正在学习数据挖掘,有以下问题。 机器学习和数据挖掘之间有什么关系? 我发现许多数据挖掘技术都与统计相关,而我“听说”数据挖掘与机器学习有很多关系。所以我的问题是:机器学习与统计学密切相关吗? 如
我有很多表的数据,例如: event_id player finish 1 a 1 1 b 2 1 c
我对 http_status_module 提供的统计数据感兴趣 特别是上游部分的统计数据。 http://nginx.org/en/docs/http/ngx_http_status_module.
除了 Cluster MBean 之外,是否有任何可以在 Akka (Java) 中启用的内置 JMX 公开监控/统计信息?我看过 Typesafe Console,但由于它需要许可证才能用于从多个节
我正在尝试在我的程序中使用“usage”统计信息来获取类似于 time 的数据工具。但是,我很确定我做错了什么。这些值似乎是正确的,但有时可能有点奇怪。我没有在网上找到好的资源。有人知道如何做得更好吗
我有一个带有统计表的 MySQL 数据库。我想以年历、月度的形式输出数据。对于没有点击率的几个月,我想花费一个“空”DIV。有两个ID。 $query = mysqli_query($db,"SELE
设置: 问题是经典概率问题的复杂形式: 70 colored balls are placed in an urn, 10 for each of the seven rainbow colors.
有哪些 Ruby gem 可以执行数据处理? 最佳答案 我知道有 3 种从 Ruby 访问 R 的方法: RinRuby RSRuby 通过 Rserve-Ruby-Client 预约 RinRuby
背景 图像领域内的一个国内会议快要召开了,要发各种邀请邮件,之后要录入、统计邮件回复(参会还是不参会等)。如此重要的任务,老师就托付给我了。ps: 统计回复邮件的时候,能知道谁参会或谁不参会。
我正在添加用户输入的几个数字并将它们添加到数组列表中。 到目前为止我的代码: package project143; import java.util.*; /** * @author -- */
正如标题所示,我需要做的是在各种 iO/Android/Windows 应用程序中跟踪各种用户事件 - 例如点击、滑动、在页面上花费的时间等。 这些应用程序基于响应式 HTML/CSS/JS,并具有简
我希望计算 HTML 表中每个唯一值的实例数,并在其自己的表中返回结果。该表是根据用户的文本输入生成的。例如,用户输入可能如下所示: Report 46 Bob Marley 4/20/2
如何使用 PHP 计算数字数组的 z 分数?我需要计算 z 分数,然后找到百分位数 (CDF)!我可以使用哪些 PHP 函数?谢谢! 最佳答案 以下代码将给出 CDF 的良好近似值(Abramowit
我只是想知道是否可以计算 GitHub 上空存储库的总数。 如果不适合所有用户,可以为自己做吗? 编辑 我已经尝试过size:0搜索,但似乎返回了很多包含数据的存储库。采用 size:0..1 之类的
public class Scanner { private HtmlProcessor hp; private String baseUrl; private int ste
我正在使用 Mule ESB 3.4。我想开发一个自定义 Java 组件来计算流收到的请求数量。流程将例如像这样: http inbound-endpoint -> counter -> vm-out
我喜欢借助 GitHub API 来统计存储库中所有开放的拉取请求和问题。我发现 API 端点 /repos/:owner/:repo 结果包含 open_issues 属性。然而,这是问题和拉取请求
如何使用 PHP 计算数字数组的 z 分数?我需要计算 z 分数,然后找到百分位数 (CDF)!我可以使用哪些 PHP 函数?谢谢! 最佳答案 以下代码将给出 CDF 的良好近似值(Abramowit
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我正在尝试以编程方式获取搜索字词列表的 Google 新闻搜索结果计数(即有多少个结果),但仅限于过去 1 年。使用用户界面搜索时,结果计数仅出现在常规搜索中,但在“工具 > 最近 > 过去一年”下时
我是一名优秀的程序员,十分优秀!