如何统计数据库的数据数量
1. count(*)
在统计一个表行数的时候,我们一般会使用 select count(*) from t。那么count(*) 是如何实现的呢?
1.1 MyISAM
在MyISAM引擎中,会把表的总行数存在磁盘上,需要的时候,直接返回即可。但是如果是加上了where 条件,就会逐行扫描,计算行数。
1.2 InnoDB
在InnnoDB中,需要把数据一行行的读出来,累计计数。
1.3 为什么InnoDB 不跟MyISAM一样把数据存起来?
因为InnoDB支持事务,由于MVCC的存在,对于返回多少行也不是很清楚,只能逐行扫描。
1.4 不同的count 有区别吗?
count() 是一个聚合函数,对于返回的结果集,逐行判断,如果不为null,则累计值加1.
- count(*), count(1), count(主键id) 返回的都是满足条件的数据总行数。
- count(主键id),InnoDB会遍历整张表,把id取出来,返回给server层,server拿到id后,判断不为null的时候,就累加1
- count(1),InnoDB会遍历整张表,不取值。server层对于返回的每一行,放数字1进去,然后判断不为null的,累加1
- MySQL 针对count(*)做了优化,执行效果较快。
- count(字段) 返回的是字段不为null的总个数。
1.5 到底该选那个count
推荐使用count(*), 按照效率排序的话是,count(*) 约等于 count(1) > count(主键Id) > count(字段)
2. 用缓存系统计数
对于更新频繁的数据库,可能会考虑使用缓存系统支持。但是缓存系统有可能丢失更新。另一种情况就是,缓存有可能在多个会话并发操作的时候,出现数据不一致的情况。
3. 用数据库计数
将表数量的技术值存放在单独的表中。
3.1 解决了崩溃失效的问题
InnoDB支持崩溃恢复不丢失数据。
3.2 解决了数据不一致问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QZ53gvSo-1606695964719)(/var/folders/r6/g3bbfdws08qbmpqyml5zpwvc0000gn/T/abnerworks.Typora/image-20201103082713688.png)]
在T3时刻,会话A尚未提交,会话B查到的表C的计数器没有加1,而且与查询最近100条记录是对应的。