为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

大家好,又见面了,我是全栈君。

点击上方“ 码农编程进阶笔记 ”,选择“置顶或者星标

文末有干货,每天定时与您相约!

统计一张表的总数量,是我们开发中常有的业务需求,通常情况下,我们都是使用 select count(*) from t SQL 语句来完成。随着业务数据的增加,你会发现这条语句执行的速度越来越慢,为什么它会变慢呢?

为什么会变慢?想要得到答案就需要知道 MySQL 是如何统计总数量的,先说一个前提吧,count(*) 的具体实现是由存储引擎实现的,也就是说不同的存储引擎实现的方式不一样。标题:为什么select count( * ) from t,在 InnoDB 引擎中比 MyISAM 慢?也是高频面试题。

InnoDB和MyISAM 是我们常用的 MySQL 存储引擎,所以主要对比一下 count(*) 在 InnoDB 和 MyISAM 中的实现:

  • 「在 MyISAM 存储引擎中,把表的总行数存储在磁盘上,当执行 select count(*) from t 时,直接返回总数据」

  • 「在 InnoDB 存储引擎中,跟 MyISAM 不一样,没有将总行数存储在磁盘上,当执行 select count(*) from t 时,会先把数据读出来,一行一行的累加,最后返回总数量」

知道了 InnoDB 和 MyISAM 引擎 count(*) 实现之后,为什么select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?应该有答案了吧,但是这个结论需要有一个前提,就是统计 SQL 不带过滤条件。如果 统计数量 SQL 语句为:select count(*) from t where x = 23,那么在 MyISAM 中就不一定比 InnoDB 快了。

「InnoDB 中 count(*) 语句是在执行的时候,全表扫描统计总数量,所以当数据越来越大时,语句就越来越耗时了」,为什么 InnoDB 引擎不像 MyISAM 引擎一样,将总行数存储到磁盘上?这跟 InnoDB 的事务特性有关,由于多版本并发控制(MVCC)的原因,InnoDB 表“应该返回多少行”也是不确定的。

不妨用一个例子来说明一下,假设现在 t 表中有 10000 条数据,现在有三个用户同时访问的会话:

  • 会话 A 先启动事务并查询一次表的总行数。

  • 会话 B 启动事务,插入一行后记录后,查询表的总行数。

  • 会话 C 先启动一个单独的语句,插入一行记录后,查询表的总行数。

为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

会话执行流程图

假设从上到下是按照时间顺序执行的,同一行语句是在同一时刻执行的。可以看出在最后时刻,三个会话返回的总行数不一样。

出现不一样的结果跟 InnoDB 存储引擎有关系,「在默认隔离级别可重复读的情况下,通过多版本并发控制(MVCC)来实现,每一行记录都需要判断自己是否对这个会话可见,因此在统计总数量时,InnoDB 只好把数据一行一行的读取出来判断,只有当前会话可见的才纳入统计中」。所以同一时刻不同会话查询到的数量就不一样。

InnoDB 引擎在 count(*)语句上也做了优化,我们知道,在 InnoDB 存储引擎中是以索引组织表的方式存储数据,主键索引树上叶子节点存放在所有的数据,而普通索引树的叶子节点是主键值,所以普通索引树会比主键索引树小很多,但是数量是一样的,也就是说遍历主键索引树和普通索引树得到的结果都是一样的。MySQL 就利用了这一特性,在 InnoDB 中执行 select count(*) from t语句时,MySQL 优化器会找到最小的那棵索引树来遍历,这样可能就可以减少加载次数,在一定程度上提升了 count(*)的执行效率。

在公众号后台回复” Mysql优化 “关键字,即可免费获取MySQL特级优化课程视频

往日精选文章

Mysql性能优化二:索引优化

MySQL索引失效的几种场景

Mysql性能优化一:SQL语句性能优化

主从配置,读写分离也是性能优化一大要点

为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111842.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 一个暑假额。。有一点进步。。要学的还有很多

    一个暑假都在安卓上了,本来眼高手低的觉得能学个差不多,没想到只学了个皮毛而已。到现在基本上了解了安卓的工作原理和一些常用api的调用,不过遇到瓶颈了,终于知道很多人劝的那句话,java基础很重要。现在体会到了,刚开始还能根据c++的理解大体写出小程序的细节,但是到后来,随着程序的增加,却是意识到需要系统的学习一下java,所以,前几天开始看李刚老师的疯狂java讲义,刚才因为出现了问题,一打开

    2022年3月8日
    43
  • matlab中的length函数「建议收藏」

    matlab中的length函数「建议收藏」在MATLAB中:size:获取数组的行数和列数length:数组长度(即行数或列数中的较大值)numel:元素总数。s=size(A),当只有一个输出参数时,返回一个行向量,该行向量的第一个元素时数组的行数,第二个元素是数组的列数。[r,c]=size(A),当有两个输出参数时,size函数将数组的行数返回到第一个输出变量,将数组的列数返回到第二个输出变量

    2022年4月30日
    143
  • Navicat 15 for orca激活码_通用破解码

    Navicat 15 for orca激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月17日
    179
  • 局域网广域网城域网的英文_城域网是内网还是外网

    局域网广域网城域网的英文_城域网是内网还是外网局域网定义:局域网是将小区域内的各种通信设备互连在一起的通信网络目前常见的局域网类型包括:以太网(Ethernet)、光纤分布式数据接口(FDDI)、异步传输模式(ATM)、令牌环网(TokenRing)、交换网Switching等,它们在拓朴结构、传输介质、传输速率、数据格式等多方面都有许多不同。局域网的典型特性:高速据率(0.1M~100Mbps),短距离(0.1km~2

    2022年10月19日
    0
  • webrtc开发入门_统计的简单应用

    webrtc开发入门_统计的简单应用WebRTC介绍及简单应用WebRTC,即WebRealTimeCommunication,web实时通信技术。简单地说就是在web浏览器里面引入实时通信,包括音视频通话等。WebRT

    2022年8月1日
    3
  • oracle触发器实例

    oracle触发器实例最近有一个需求,一个数据库的表在插入和删除的时候另外一个数据库中的表也做相应的操作。我的想法是1.首先两个数据库可以连接,通过dblink可以解决。2.建立插入和删除才能触发的触发器。直接上代码createorreplacetriggersynch_useridafterinsertordeleteoneosoperatorFOREACHROW–每一行触发一次…

    2022年7月27日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号