Mysql是怎样实现统计一张表行数
Contents
开发时时如何统计一张表的总函数,一般是
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;否则不加
- count(主键id),InnoDB引擎会遍历整张表,将id值取出来给server层;判断不可能为空,按行累加
- count(1),InnoDB引擎会遍历整张表,当不取值,放个‘1’给server层;判断不可能为空,按行累加
- count(字段),InnoDB引擎会遍历整张表,先判断‘字段’是否定义
not null
,如果是直接累加;没定义not null
,判断是否为null,不是null才累加 - count(*),做了优化,并不是把全部字段取出来,而是按行累加
- 按照效率排序的话,count(字段)<count(主键id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。
三、自己计数方式有哪些方法
1.用缓存统计保存计数(redis)
- 存在丢失更新问题(系统异常)
- 逻辑上不精确(出现查的时候,可能有新数据更新/插入)
2.数据库中保存计数
- 可以去除系统崩溃导致的更新问题
- 可以用事务,从而使逻辑上精确
Author zhuyhan
LastMod 2020-04-15