声明:本文章内容是根据极客时间中林晓斌的课程《MYSQL45讲》,经过学习,加以自己的理解形成的笔记。具体原文可以到官网进行阅读。如有侵权请,告知删除。
1.count(*)的实现方式
- MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高;
- InnoDB引就比较麻烦,每次执行count(*)的时候都需要把数据一行以上的从引擎读出来,然后累积计数;
2.为什么InnoDB不能把数字存储起来
这是因为多版本并发控制(MVCC)的原因,不同事务由于隔离级别的原因导致,每个事务看到的行数其实是不确定。所有也就无法存储一个固定的数值
所以当我们直接使用count(*)的时候,会遍历全表从而引发性能问题
3.解决方法
把这个计数直接放到数据库里单独一张计数表。(InnoDB的日志机制,可让他支持崩溃恢复数据不丢失数据)。
那我们在看一下多事务情况会不会出现不准确的情况:
因为事务A还没提交 ,所以插入的操作对会话B不可见,这样会话B 逻辑上的操作都是正确的。
4. count的几种用法
- count(主键 id) InnoDB引擎会遍历整张表,把每一行的ID都取出来,返回给server层。
- count(1) InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去
- count(字段) :
1、如果字段定义是not null的话,读取这个字段,判断不为null,按行累加
2、如果这个字段定义允许为null,还需要再判断 可能为null 然后按行累加 - count(*)这是一个例外,并不会吧全部的字段取出来,而且做了专门的优化,不取值,按行累加
- count(字段)<count(主键 id)<count(1)≈count(*)