MySQL语句执行过程及count(*)效率问题
MySQL语句执行过程及count(*)效率问题
SQL的执行过程
下面我给出的是MySQL的基本架构示意图,并且清楚的展示了SQL语句的执行过程:
连接器:
连接器负责跟客户端建立连接、获取权限、维持和管理连接。客户端如果太长时间没动静,连接器就会自动将它断开。查询缓存:
将之前查询的结构进行缓存,key是查询语句。但是MySQL 8.0版本直接将查询缓存的整块功能删掉了。分析器:
对SQL语句先进行词法分析再进行语法分析。优化器:
会对语句进行优化判断。执行器:
先校验权限,如果校验通过就会根据表的引擎定义,去使用这个引擎提供的接口,最后将结果组成结果集返回给客户端。
count(*)这么慢
你首先要明确的是,在不同的MySQL引擎中,count(*)有不同的实现方式:
- MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高;
- 而InnoDB引擎就麻烦了,它执行count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。
由于多版本并发控制(MVCC)的原因,InnoDB表“应该返回多少行”也是不确定的
按照效率排序的话,count(字段)<count(主键id)<count(1)≈count(*)
,所以我建议你,尽量使用count(*)
。
其他方式:
用缓存系统保存计数
在并发系统里面,我们是无法精确控制不同线程的执行时刻的,因为存在图中的这种操作序列,所以,我们说即使Redis正常工作,这个计数值还是逻辑上不精确的。
在数据库保存计数
把这个计数直接放到数据库里单独的一张计数表C中,并利用利用“事务”这个特性把问题解决掉。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 goMars的学习随记!
评论