开发时时如何统计一张表的总函数,一般是select count(*) form t,但是随着表数据大,会越查越慢

一、不同实现COUNT的方式

MyISAM引擎

查询整表总函数:select count(*) form t

  • 把一个表的总行数写入磁盘上,count(*)直接返回这个数,效率很高(不支持事务)
  • 前提条件:不能加有任何WHERE条件

InnoDB引擎

方式一:show table status命令TABLE_ROWS可以显示表行数

  • 优点:查询得很快
  • 缺点:索引统计的值是通过采样估计来的,结果不准(错误达到40%-50%)

方式二:查询整表总函数:select count(*) form t

  • 优点:结果准确
  • 缺点:需要遍历全表,但是会导致性能问题

问:为什么InnoDB不把统计数字存起来?

  • InnoDB是多个版本控制的(MVCC),同一个时刻不同会话统计出来的值可能不一致(事务隔离级别)

问:InnoDB的count(*)如何优化查询?

  • InnoDB优化器会选择最小的索引树来查询的;主键索引树的叶子结点是数据,普通索引数额叶子结点是主键,因此普通索引树比主键索引树小很多

二、Count()的不同用法

count()函数是聚合函数,对于返回的结果集,一行行地判断,如果函数的参数不是NULL,累计值加1;否则不加

  1. count(主键id),InnoDB引擎会遍历整张表,将id值取出来给server层;判断不可能为空,按行累加
  2. count(1),InnoDB引擎会遍历整张表,当不取值,放个‘1’给server层;判断不可能为空,按行累加
  3. count(字段),InnoDB引擎会遍历整张表,先判断‘字段’是否定义not null,如果是直接累加;没定义not null,判断是否为null,不是null才累加
  4. count(*),做了优化,并不是把全部字段取出来,而是按行累加
  5. 按照效率排序的话,count(字段)<count(主键id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。

三、自己计数方式有哪些方法

1.用缓存统计保存计数(redis)

  • 存在丢失更新问题(系统异常)
  • 逻辑上不精确(出现查的时候,可能有新数据更新/插入)

2.数据库中保存计数

  • 可以去除系统崩溃导致的更新问题
  • 可以用事务,从而使逻辑上精确