极客时间《Mysql实战45讲》的笔记:
我们在开发的时候,经常用count()统计总条数,然后根据这个总条数,返回给前端进行分页,那么count()的底层是怎么实现的。
count(*)的实现方法
在不同的引擎中,count(*)的实现机制不同
1.MyISAM 引擎把一个表的总行数存在了磁盘上,,因此执行 count(*) 的时候会直接返回这个数,效率很高(加上where条件就应当别论了)
2.而 InnoDB 引擎就麻烦了,它执行 count(*) 的的时候,需要把数据一行一行的从引擎里读出来,然后累积计数。
那为什么InnoDB不跟MyISAM一样,把数字存起来呢?
因为InnoDB的多版本并发控制(MVCC)的原因。即便同一时刻多个查询,InnoDB也不确定那返回多少行。
image根本的原因是因为InnoDB支持事务,可重复读默认是隔离级别,是通过多版本并发控制,也就是 MVCC来实现的。查询的count(*),要根据每个会话的情况而决定的。
对频繁操作count(*),有什么方法
1.用缓存系统保存计数
这种方法是十分容易想到的,但他有2点致命的缺陷。
1.数据易丢失
redis的数据是不能永久的留在内存里的,虽然redis有持久化的机制,即便是这样,仍然可能丢失,假设:你的在数据库插入一条数据,redis这时候加1,突然redis异常重启,然后你把持久化的数据读进去,刚刚加1的数据就丢了。
2.逻辑上不精确
有这样一个页面,它要求显示总条数,还要显示最近的100条。
image进行上面的操作,有问题吧。
2.在数据库保存计数
保存在数据库中,首先解决了数据丢失的问题,
因为InnoDB支持事务的缘故,也解决了计数上不精确的问题。
image今天就记录到这里啊。
image
网友评论