InnoDB 引擎中 count(*)速度?

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

不一定。分两种情况。
1.如果在查询语句中带有where 条件的话。两种表的操作是一样的。
2.如果查询SQL语句不带有where 条件的话。MyISAM 比InnoDB 快。因为在MyISAM 引擎中把一张表的总行数存储在了磁盘上,查询的时候直接返回就行了。而InnoDB 需要全表扫描,计算总行数,所以慢。
为什么 InnoDB不能和MyISAM一样呢?因为事务特性决定,多版本并发控制(MVCC)存在,导致不同时刻看到的结果是不一样的。

count(*) 的具体实现是由存储引擎实现的,也就是说不同的存储引擎实现的方式不一样。

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

  • 统计SQL不带where 条件时:
    在MyISAM 存储引擎中,把表的总行数存储在磁盘上,当执行 select cout() from t 时,直接返回总数据的数量。
    在InnoDB 存储引擎中,并没有存储总行数在磁盘上,当执行 select cout(
    ) from t 时,会先把数据读出来,一行一行的累加。最后返回总数量。

  • 统计SQL带where 条件时:
    都是一行一行累加。最后返回数量。(ps:MyISAM 中存储的表的总数量)

InnoDB 中count(*) 语句是在执行的时候,全表扫描统计总数量。当数据量越来越大时,语句就会很慢。InnoDB为什么不记录总行数到磁盘上?这和InnoDB的事务特性有关,由于多版本并发控制(MVCC)原因,InnoDB表在查询的时候“应该返回多少行”是不确定的。

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

  • 会话 A 先启动事务并查询一次表的总行数。
  • 会话 B 启动事务,插入一行后记录后,查询表的总行数。
  • 会话 C 先启动一个单独的语句,插入一行记录后,查询表的总行数。
    在这里插入图片描述
    假如从上到下是按照时间顺序执行的,同一行语句是在同一时间执行的。可以看出在最后时刻。三个回话返回的总行数不一样。
    出现不一样的结果跟InnoDB存储引擎有关。在默认隔离级别 可重复读的情况下,通过多版本并发控制(MVCC)来实现,每一行记录都需要判断自己是否对这个会话可见,因此在统计总数量时,InnoDB引擎只有把数据一行一行的读取出来判断,只有当前会话可见才被统计进去。所以同一时刻不同会话查询到的数量就不一样。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值