count()这么慢,我该怎么办读后总结

计算一个表的行数语句:
select count(*) from t;
innodb中这条语句的查询时间会随着表记录增加而增加。

count()是实现方式
count(
)是在引擎层面实现的,不同的引擎有不同的实现。
1.MYISAM是将表的总行数存在磁盘上。count()会直接返回这个值,很高效,但是如果加上了where条件,也需要遍历。
2.Innodb在执行count(
)的时候需要一行一行从引擎中读出来。所以记录越多,查询越慢。

为什么Innodb不将总行数存起来?

同一时刻的多个查询 ,由于MVCC以及事务隔离性,innodb表要返回多少行是不确定的。在RR隔离级别下

mysql还是对count(*)做了优化的,innodb是索引组织表,主键索引树的叶子节点是数据,而普通索引树的叶子节点是主键值。所以普通索引比主键索引树小很多。在保证逻辑正确的情况下,尽可能少的扫描数据量,是数据库设计的通用法则之一。

show table status命令输出中有TABLE_ROWS用于表当前有多少行,但是这不是一个精确值是一个统计计数。

场景:有一个页面要经常显示交易系统的操作记录总数
记录量较大的情况下,肯定不能一直用count()
方案:
1.用缓存系统保存计数
用一个redis kv来保存表的总行数,innodb insert后 redis val++,innodb delete后redis val–
风险是:
1.丢失更新。innodb insert后,redis异常重启后,丢失这个val++操作,一般redis重启后都会去mysql将数据重新加载一下,count(
)。
2.值逻辑上不精准。有一个页面既要操作记录总数,又要最近前100条操作记录。那么既要从redis取总数,又要去mysql去前100条记录。
如何定义不精准:
1.从mysql中读取100条记录中有最新的记录,redis没有val++
2.从mysql中读取100条记录中没有最新的记录,redis中val++
其实为什么会出现这种不一致,由于mysql与redis不在同一个系统中,并没有做数据一致性的同步。
2. 在数据库保存计数。如果我们把这个计数直接放在mysql的一张计数表中,利用事务的特定,在更新对于查询不可见。这样查出来的100条数据与记录总数都是一致的。

不同的count用法性能:
count(字段)<count(主键)<count(1)=count(*)

count(*),count(1),count(主键)都表示返回满足条件的结果集的总行数,
count(字段)表示字段不为NULL的总个数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值