众所周知,mysql常用的引擎就两个:MyISAM和InnoDB。
InnoDB有很多MyISAM没有的东西,如支持事务、支持行锁、支持MVCC…
但是
MyISAM在执行count()的时候是真的快,这时候的InnoDB简直就是个弟弟。
对比如下:
实验环境
mysql版本信息
表数据量354w+
实验过程
1.不带条件的count()
将数据表引擎切换为InnoDB,花费102s左右
InnoDB执行不带条件count(),第一次花费28s左右,之后平均1s左右
将数据表引擎切换为MyISAM,花费53s左右
MyISAM执行不带条件count(),平均0.00027s左右
2.带条件的count()
MyISAM执行带条件count(),平均1.3s左右
InnoDB执行带条件count(),平均1.5s左右
实验结论
不带条件count():
MyISAM执行时间短到可以忽略不计
InnoDB第一次执行count()需要大概28s,之后每次平均在1s左右。
原因:
Myisam内置了一个计数器,直接将表的总行数存储在磁盘上
InnoDB第一次需要全表扫描统计总行数,所以很慢。
带条件count():
MyISAM和InnoDB执行时间差不多。
实验所用命令:
//统计查询 SELECT COUNT(*) AS tp_count FROM cmf_users_loginrecord
where addtime between 1540111489 and 1543653889;
//查询表结构 show create table cmf_users_loginrecord
;
//查询profiles是否开启 show variables;
//开启profiles set profiling = 1;
//查询sql执行时间 show profiles;
//切换表引擎 ALTER TABLE cmf_users_loginrecord
ENGINE=InnoDB;
为什么 InnoDB 不跟 MyISAM 一样,也把数字存起来呢?
这是因为即使是在同一个时刻的多个查询,由于多版本并发控制(MVCC)的原因,InnoDB表“应该返回多少行”也是不确定的。 这和
InnoDB 的事务设计有关系,可重复读是它默认的隔离级别,在代码上就是通过多版本并发控制,也就是 MVCC
来实现的。每一行记录都要判断自己是否对这个会话可见,因此对于count(*) 请求来说,InnoDB
只好把数据一行一行地读出依次判断,可见的行才能够用于计算“基于这个查询”的表的总行数。
https://www.jianshu.com/p/ec52c5b72582
PS:
如何查看sql执行时间
1 show profiles;
2 show variables;查看profiling 是否是on状态;
3 如果是off,则 set profiling = 1;
4 执行自己的sql语句;
5 show profiles;就可以查到sql语句的执行时间;