dbgrideh 为什么只一行_Mysql性能优化:为什么count(*)这么慢?

导读

  • 在开发中一定会用到统计一张表的行数,比如一个交易系统,老板会让你每天生成一个报表,这些统计信息少不了sql中的count函数。
  • 但是随着记录越来越多,查询的速度会越来越慢,为什么会这样呢?Mysql内部到底是怎么处理的?
  • 今天这篇文章将从Mysql内部对于count函数是怎样处理的来展开详细的讲述。

count的实现方式

  • 在Mysql中的不同的存储引擎对count函数有不同的实现方式。
  • MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高(没有where查询条件)。
  • InnoDB引擎并没有直接将总数存在磁盘上,在执行count(*)函数的时候需要一行一行的将数据读出来,然后累计总数。

为什么InnoDB不将总数存起来?

  • 说到InnoDB相信读者总会想到其支持事务的特性,事务具有隔离性,如果将总数存起来,怎么保证各个事务之间的总数的一致性呢?不明白的看下图:

a48e3e8c762d052bc814f3e4ad1b2826.png
  • 事务A事务B中的count(*)的执行结果是不同的,因此InnoDB引擎在每个事务中返回多少行是不确定的,只能一行一行的读出来用来判断总数。

如何提升count效率

  • InnoDB对于如何提升count(*)的查询效率,网上有多种解决办法,这里主要介绍三种,并分析可行性。

show table status

  • show table status这个命令能够很快的查询出数据库中每个表的行数,但是真的能够替代count(*)吗?
  • 答案是不能。原因很简单,这个命令统计出来的值是一个「估值」,因此是不准确的,官方文档说误差大概在40%-50%
  • 因此这种方法直接pass,不准确还用它干嘛。

缓存系统存储总数

  • 这种方法也是最容易想到的,增加一行就+1,删除一行就-1,并且缓存系统读取也是很快,既简单又方便的为什么不用?
  • 缓存系统和Mysql是两个系统,比如redisMysql这两个是典型的比较。两个系统最难的就是在高并发下无法保证数据的一致性。通过以下两图我们来理解一下:

35978d8fae0637dfdd53ee6738494455.png

78bfd363a111f13c057e50187dd10ec3.png
  • 通过上面两张图,无论是redis计数+1还是insert into user先执行,最终都会导致数据在逻辑上的不一致。第一张图会出现redis计数少了,第二张图虽然计数正确了但是并没有查询出插入的那一行数据。
  • 在并发系统里面,我们是无法精确控制不同线程的执行时刻的,因为存在图中的这种操作序列,所以,我们说即使Redis正常工作,这个计数值还是逻辑上不精确的。

在数据库保存计数

  • 通过缓存系统保存的分析得知了使用缓存无法保证数据在逻辑上的一致性,因此我们想到了直接使用数据库来保存,有了「事务」的支持,也就保证了数据的一致性了。
  • 如何使用呢?很简单,直接将计数保存在一张表中(table_name,total)。
  • 至于执行的逻辑只需要将缓存系统中redis计数+1改成total字段+1即可,如下图:

e40e484330c1f15c85d08e84ceb44331.png
  • 由于在同一个事务中,保证了数据在逻辑上的一致性。

不同count的用法

  • count()是一个聚合函数,对于返回的结果集,一行行地判断,如果count函数的参数不是NULL,累计值就加1,否则不加。最后返回累计值。
  • count的用法有多种,分别是count(*)、count(字段)、count(1)、count(主键id)。那么多种用法,到底有什么差别呢?当然,「前提是没有where条件语句」。
  • 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(*)。」
  • 「注意」:这里肯定有人会问,count(id)不是走的索引吗,为什么查询效率和其他的差不多呢?陈某在这里解释一下,虽然走的索引,但是还是要一行一行的扫描才能统计出来总数。

总结

  • MyISAM表虽然count(*)很快,但是不支持事务;
  • show table status命令虽然返回很快,但是不准确;
  • InnoDB直接count(*)会遍历全表(没有where条件),虽然结果准确,但会导致性能问题。
  • 缓存系统的存储计数虽然简单效率高,但是无法保证数据的一致性。
  • 数据库保存计数很简单,也能保证数据的一致性,建议使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jmeter 高并发测试报告_JMeter分布式测试

一、为什么要使用分布式测试按照一般的压力机配置&#xff0c;jmeter的GUI模式下(Windows)&#xff0c;最多支持300左右的模拟请求线程&#xff0c;再大的话&#xff0c;容易造成卡顿、无响应等情况&#xff0c;这是限于jmeter其本身的机制和硬件配置。有时候为了尽量模拟业务场…

半圆阴影_六年级数学:怎么求阴影部分面积?正方形与半圆,割补法常考题

欢迎您来到方老师数学课堂&#xff0c;请点击上方蓝色字体&#xff0c;添加关注。所有的视频内容&#xff0c;全部免费&#xff0c;请大家放心关注&#xff0c;放心订阅。六年级数学&#xff1a;怎么求阴影部分面积&#xff1f;正方形与半圆&#xff0c;割补法常考题。大家先在…

c语言判断整数_用c++编写闰年的判断基础程序

其实c语言与c语言有太多共同的东西&#xff0c;学习过c语言再学习c语言就显得轻而易举。当然学过了c再去学习c语言也是有一些帮助的(但是个人不提倡先学习c在学c语言)。由于现在经常看见有关闰年的程序&#xff0c;风式各样&#xff0c;眼花缭乱&#xff0c;些许凌乱&#xff0…

cat日志 搜索_大日志,看我如何对付你

在服务器接口测试中&#xff0c;我们经常会和各种日志打交道。一旦测试时服务端出现了问题&#xff0c;而单凭服务端的日志又不能发现问题原因的时候&#xff0c;往往开发要向我们测试人员询问客户端这边的情况&#xff0c;希望看看我们能不能提供一些有用信息&#xff0c;如错…

加载gif动图_GIF生成神器——ScreenToGif

每次需要做一个动图展示时&#xff0c;总是感觉很头疼。截图吧&#xff0c;需要的图片太多&#xff1b;录视频吧&#xff0c;文件太大&#xff1b;做动图吧&#xff0c;太麻烦。今天推荐的这个软件或许能够解决大家这个困惑&#xff0c;今天推荐的是动图生成神器——ScreenToGi…

java 修改最大nio连接数_关于java流的几个概念:IO、BIO、NIO、AIO,有几个人全知道?...

关于同步、阻塞的知识我之前的文章有介绍&#xff0c;所以关于流用到这些概念与之前多线程用的概念一样。下面具体来看看java中的几种流IO/BIOBIO就是指IO&#xff0c;即传统的Blocking IO,即同步并阻塞的IO。这也是jdk1.4之前的唯一选择&#xff0c;依赖于ServerSocket实现&am…

python扫雷 广度优先_广度优先搜索(BFS)解题总结

定义 广度优先搜索算法&#xff08;Breadth-First-Search&#xff09;&#xff0c;是一种图形搜索算法。 简单的说&#xff0c;BFS是从根节点开始&#xff0c;沿着树(图)的宽度遍历树(图)的节点。 如果所有节点均被访问&#xff0c;则算法中止。 BFS同样属于盲目搜索。 一般用队…

python裁剪图片并保存_python – 如何从图像中剪切轮廓并将其保存到新文件中

大家好,这是我的第一个问题所以请保持温和.我有一个计算机视觉领域的项目,我是新的,我会很感激一些帮助.我有一个pcb的图像,我的(首先)任务是从背景中切断电路板并将其保存到新文件.如果结果只是没有灰色背景的普通pcb,那就没问题了. 我到目前为止尝试的是,首先使用阈值将图像转…

flash代码_Flash如何对制作文件进行优化

对FLASH进行优化分为两方面&#xff0c;一方面是代码上的优化&#xff0c;主要是通过优化提高FLASH性能&#xff0c;降低CPU占用和内存使用。另一方面是资源的优化&#xff0c;这方面的优化是为了减小编译后的文件大小以及制作文件的大小&#xff0c;因为如果不进行相应的优化&…

deepin系统转为windows_windows系统下安装深度系统deepin

前期准备DiskGenius(用来扩展分区)deepin-20-amd64.iso(深度系统镜像文件)相关文件下载首先下载安装时要用的工具&#xff0c;分别为:DiskGenius , UltraISODiskGenius是一款磁盘工具&#xff0c;创建系统分区。UltraISO是用来打开系统光盘镜像文件工具。Win8/8.1/10无需下载Ul…

软件开发模型_QT开发(二十三)——软件开发流程

一、软件开发流程简介软件开发流程是通过一系列步骤保证软件产品的顺利完成&#xff0c;是软件产品在生命周期内的管理学。软件开发流程的本质是软件开发流程与具体技术无关&#xff0c;是开发团队必须遵守开的规则。二、常见软件开发流程模型常见的软件开发流程模型包括即兴模…

python3.6.2用pyinstaller3.4报错_OceanBase 2.2 版本体验:用 BenchmarkSQL 跑 TPC-C

OB君&#xff1a;好消息&#xff01;「 OceanBase 2.2 版本 」正式上线官网啦&#xff01;&#xff08;点击阅读原文即可直接下载&#xff09;OceanBase 2.2版本是成功支撑2019年天猫双11大促的稳定版本&#xff0c;同时也是用于TPC-C测试且荣登TPC-C性能榜首的版本。我们将在接…

hive窗口函数_Hive sql窗口函数源码分析

在了解了窗口函数实现原理 spark、hive中窗口函数实现原理复盘 和 sparksql比hivesql优化的点(窗口函数)之后&#xff0c;今天又撸了一遍hive sql 中窗口函数的源码实现&#xff0c;写个笔记记录一下。简单来说&#xff0c;窗口查询有两个步骤&#xff1a;将记录分割成多个分区…

容大打印机ip修改工具_M1芯片版Mac无法连接打印机怎么办?

文末有优惠券在入手了M1芯片版MacBook Pro后&#xff0c;昨天我打算连接一下实验室的打印机。这个打印机的型号是HP LaserJet Professional M1213nf MFP&#xff0c;在同一个局域网内通过搜索IP即可连接。在我的旧设备2015款MacBook Air上&#xff0c;很轻松就连接了打印机。可…

语音对讲软件_三款语音转文字工具,语音输入,高效转换,准确率高

关于语音转文字的软件我在之前讲了很多&#xff0c;有些人听了也用了&#xff0c;效果不错&#xff0c;有些人看了就忘了&#xff0c;主要是不知道用它干嘛&#xff0c;其实语音转文字的软件主要功能就是为了让自己在写作的时候可以减少时间&#xff0c;提高效率&#xff0c;其…

野火stm32呼吸灯程序_说一说STM32启动过程

STM32上电后是怎么启动的&#xff1f;main函数之前单片机都做了些什么&#xff1f;带着这些疑问我们开始进入游戏。。。。。首先&#xff0c;开局一张图&#xff0c;过程全靠编&#xff0c;如有说错的地方望能指正启动大致流程1- 上电启动或者硬件复位2- 单片机从0x00地址开始执…

apache启动失败_请检查相关配置.√mysql5.1已启动._1、Apache启动失败,请检查相关配置-百度经验...

前几天电脑系统崩溃了,后边到服务中心重新恢复了系统,但是回来使用APMServ 5.2.6发现:1、Apache启动失败,请检查相关配置。√MySQL5.1已启动。系统的各种服务我都检查过了,都是正常开启的,百思不得其解,后边在百度上搜索一篇文章有个例子照做了以后结果成功了。---------------…

职业规划纵向横向_收下这份《职业规划喂饭式指南》

果不其然&#xff01;上篇文章发布后&#xff0c;我收到了被拿来举反例的网友小哥的抗议~~~讲道理&#xff0c;最后他拿到的Offer还是十分不错的&#xff0c;从此以后我的朋友圈又多了一位第一手保真瓜主&#xff0c;他好我也好~那么本期《职业规划喂饭式指南》来喽&#xff01…

javascript字典中添加数组_如何在 JavaScript 中更好地使用数组

在 freeCodeCamp 社区阅读原文。本文短小精悍&#xff0c;我保证。在过去的数个月里&#xff0c;我注意到在我审阅的 pull request 中有四个&#xff08;关于数组使用的&#xff09;错误经常出现。同时&#xff0c;我自己也会犯这些错误&#xff0c;因此有了这篇文章。让我们一…

mysql join图解_MySQL中Join算法实现原理分析[多图]

在MySQL 中&#xff0c;只有一种 Join 算法&#xff0c;就是大名鼎鼎的 Nested Loop Join&#xff0c;他没有其他很多数据库所提供的 Hash Join&#xff0c;也没有 Sort Merge Join。顾名思义&#xff0c;Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据&#…