zoukankan      html  css  js  c++  java
  • 为什么 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 先启动一个单独的语句,插入一行记录后,查询表的总行数。

    会话执行流程图

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

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

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

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

    往日精选文章

    Mysql性能优化二:索引优化

    MySQL索引失效的几种场景

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

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

  • 相关阅读:
    测试思想-测试设计 史上最详细测试用例设计实践总结 Part2
    测试思想-测试设计 史上最详细测试用例设计实践总结 Part1
    loadrunner 脚本开发-参数化之将内容保存为参数、参数数组及参数值获取Part 2
    loadrunner 脚本开发-参数化之将内容保存为参数、参数数组及参数值获取
    测试思想-测试计划 软件测试方法与测试策略简述
    测试思想-文档评审 关于需求评审
    loadrunner 运行脚本-命令行运行脚本
    loadrunner 运行脚本-Run-time Settings-Browser Enmulation设置详解
    loadrunner 运行脚本-Run-time Settings-ContentCheck简单设置
    python 全栈开发,Day53(jQuery的介绍,jQuery的选择器,jQuery动画效果)
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15452878.html
Copyright © 2011-2022 走看看