为什么 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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QGridLayout中multi cell处理

    QGridLayout中multi cell处理

    2021年7月25日
    63
  • googlenet网络模型简介_网络参考模型

    googlenet网络模型简介_网络参考模型一、GoogleNet模型简介  GoogleNet和VGG是2014年imagenet竞赛的双雄,这两类模型结构有一个共同特点是godeeper。跟VGG不同的是,GoogleNet做了更大胆的网络上的尝试而不是像VGG继承了Lenet以及AlexNet的一些框架,该模型虽然有22层,但大小却比AlexNet和VGG都小很多,性能优越。深度学习以及神经网络快速发展,人们容易通过更高性能的

    2022年8月14日
    7
  • C语言中char、short、int、long各占多少字节

    C语言中char、short、int、long各占多少字节1byte=8bit一个字节占8个二进制位windows操作系统,32位机中,char:1个字节short:2个字节int:4个字节long:4个字节以下是windows操作系统,32位机下的代码测试结果(32位机中,指针占4个字节,如变量e):windows操作系统,64位机中,char:1个字节…

    2022年5月5日
    69
  • 单例模式的使用总结

    单例模式的使用总结目录一、单例模式的定义和应用场景(一)定义及基本要点(二)应用场景二、饿汉式单例模式(一)基本代码展示分析(二)基本分析和建议三、懒汉式单例模式(双重检查锁)(一)基本代码展示分析(二)基本分析和建议四、静态内部类实现单例模式(一)基本代码展示分析(二)基本分析和建议五、注册式单例模式(一)枚举式单例模式代码及分析:(EffectiveJa…

    2022年7月25日
    8
  • Mac maven环境变量配置[通俗易懂]

    Mac maven环境变量配置

    2022年1月17日
    51
  • java copyproperties_java中 BeanUtils.copyProperties的用法

    java copyproperties_java中 BeanUtils.copyProperties的用法BeanUtils提供了对java发射和自省API的包装,这里对BeanUtils.copyProperties的用法做一个小小的介绍。通过函数名可以知道,copyProperties函数是对属性进行拷贝,该函数有两个参数,一个是原始的数据,另一个是接收这些属性的数据。这里给大家介绍一个我遇到的一个坑:在不同的jar包中,该函数的两个参数的位置不一样,有一种是copyProperties(java…

    2022年10月3日
    1

发表回复

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

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