众所周知,mysql常用的引擎就两个:MyISAM和InnoDB。
InnoDB有很多MyISAM没有的东西,如支持事务、支持行锁、支持MVCC…
但是
MyISAM在执行count()的时候是真的快,这时候的InnoDB简直就是个弟弟。

对比如下:

实验环境

mysql版本信息

mysql sum超级慢 mysql sum效率_innodb


表数据量354w+

mysql sum超级慢 mysql sum效率_mysql_02

实验过程

1.不带条件的count()

将数据表引擎切换为InnoDB,花费102s左右

mysql sum超级慢 mysql sum效率_innodb_03


InnoDB执行不带条件count(),第一次花费28s左右,之后平均1s左右

mysql sum超级慢 mysql sum效率_执行时间_04

将数据表引擎切换为MyISAM,花费53s左右

mysql sum超级慢 mysql sum效率_mysql_05

MyISAM执行不带条件count(),平均0.00027s左右

mysql sum超级慢 mysql sum效率_innodb_06

2.带条件的count()

MyISAM执行带条件count(),平均1.3s左右

mysql sum超级慢 mysql sum效率_执行时间_07


mysql sum超级慢 mysql sum效率_执行时间_08

InnoDB执行带条件count(),平均1.5s左右

mysql sum超级慢 mysql sum效率_innodb_09


mysql sum超级慢 mysql sum效率_innodb_10

实验结论

不带条件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语句的执行时间;