声明:本文章内容是根据极客时间中林晓斌的课程《MYSQL45讲》,经过学习,加以自己的理解形成的笔记。具体原文可以到官网进行阅读。如有侵权请,告知删除。

1.count(*)的实现方式

  • MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高;
  • InnoDB引就比较麻烦,每次执行count(*)的时候都需要把数据一行以上的从引擎读出来,然后累积计数;

2.为什么InnoDB不能把数字存储起来

这是因为多版本并发控制(MVCC)的原因,不同事务由于隔离级别的原因导致,每个事务看到的行数其实是不确定。所有也就无法存储一个固定的数值
所以当我们直接使用count(*)的时候,会遍历全表从而引发性能问题

3.解决方法

把这个计数直接放到数据库里单独一张计数表。(InnoDB的日志机制,可让他支持崩溃恢复数据不丢失数据)。
那我们在看一下多事务情况会不会出现不准确的情况:
MySQL学习笔记之count(*)(十三)
因为事务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(*)

相关文章: