数据库专题——深入理解count(*)为什么这么慢

   日期:2020-09-16     浏览:115    评论:0    
核心提示:一文搞懂count(*count(*)的实现方式功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入之前在开发一个交易平台过程中,有遇到过需要计算交易记录总数。可能很多人会和我当初想得一样一条select count(*)

深入理解count*为什么这么慢

  • 不同存储引擎的实现方式
  • InnoDB为什么不存起来
  • MySQL的优化
  • show tables status不准确

  曾经在依次面试中被问到过这么一个问题,假设开发一个交易平台过程中,有遇到过需要计算交易记录总数的情况该怎么办。可能大多数人的回答都是用select count(*) from t 不就搞定了吗 但是,面试官又问到随着系统中记录数越来越多,这条语句执行得越来越慢。那么为什么这么慢呢,今天我们就来聊一聊原因吧。

不同存储引擎的实现方式

 MySQL在不同的存储引擎中,count(*)的实现方式也不相同。

  1. 一般来说MyISAM引擎效率比较高,因为它是把一个表的总行数存到了磁盘上,因此执行count(*)的时候回直接返回计数值。但是如果加上where的话,MyISAM的表也不能反应这么快。
  2. InnoDB引擎它执行count(*)的时候比较麻烦,它需要把数据一行一行地从引擎里面读出来,然后再进行累计计数。

InnoDB为什么不存起来

 即使同一时刻的多个查询,由于多版本并发控制(MVCC)的原因,事务T启动的时候会创建一个视图read-view,InnoDB的表根据视图进行计数的。因此不能确定应该返回多少行。下面我们举个例子来解释一下:
 假设表t1有5000条记录,三个用户并行的会话。

  • 会话1先启动事务并查询一次表的总行数
  • 会话2先启动事务,插入一条记录后再查询表的总行数
  • 会话3先启动一个单独的语句,插入一条语句后再查询表的总行数。
会话1 会话2 会话3
begin;
select count(*) from t1;
insert into t1 ()
begin;
insert into t1 ()
select count(*) from t1(返回5000) select count(*) from t1(返回5002) select count(*) from t1(返回5001)

 最后,三个会话会同时查询表t1的总行数,但拿到的结果却不相同。这个原因其实和事务的设计有一定关系。一般默认隔离级别是可重复读(REPATABLE-READ)

而可重复读是通过MVCC来实现。每一行记录都要判断是否对这个会话可见。因此就count(*)来说,InnoDB只好把数据逐行地读出并判断,只有可见的行才能被用来计算表的总行数。

MySQL的优化

 MySQL实际上是做了优化的,InnoDB是索引组织表,主键索引树的叶子节点是数据,而普通索引树的叶子节点是主键值。因此普通索引树比主键索引树小很多。对于count(*)操作遍历哪棵树逻辑上来讲结果都是一样的。因此,为了遵循减少数据量遍历的原则,MySQL的优化器会找到最小的那颗树来进行遍历。
  这里提到的主键索引树和普通索引树是什么意思?我们来举个例子:
假设有张InnoDB表t (id PK, name KEY, sex, flag)
表中有四条记录:

1, song, m, A

3, zhang, m, A

5, li, m, A

9, wang, f, B

 则它们的索引树如下图所示:

 假设要执行语句select * from t where name=’song’;

(1)首先在name普通索引上查询到PK=1;

(2)再在主键索引树上查询到(1,song, m, A)的行记录;

show tables status不准确

  其实MySQL有条命令show tables status命令执行结果中有条Rows能用于显示表有多少行,比如我们有张表结构是这样的

 插入数据后,执行show table status命令结果如下:

 这条命令执行比count(* )快,那用它来代替count(*)岂不是很快。但是不行,为什么呢?
 它不够准确,因为它的值是根据MySQL采样统计估算出来的,官方统计,误差还是可能会达到40%-50%。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服