赞
踩
MyISAM引擎把表的总行数存在磁盘上,在没有where条件的时候,如果执行count(*),会直接返回这个数。
InnoDB引擎在执行count(*)时,需要把数据一行一行地读出来,累积计数。这是由于InnoDB事务默认的隔离级别是可重复读,可重复读是通过多版本并发控制(MVCC)实现的,一个会话在执行count(*)的时候,要依次判断表中的每一行是否可见,可见的行进行累积计数。此外,InnoDB是索引组织表,普通索引树比主键索引树小很多,所以在进行count(*)时,优化器会寻找最小的那棵树来遍历。
把计数直接放到数据库中单独一张计数表中,当表中插入一行的时候,就计数表中的计数值就加1,当删除一行的时候,计数表中的计数值就减1。由于InnoDB是支持崩溃恢复数据的,因此这种做法不用担心因系统崩溃而导致的计数丢失。此外,InnoDB是支持事务的,默认的隔离级别是可重复读,因此对于可以保证数据的逻辑一致性。
如图可见,如果使用缓存保存计数,那么由于在并发系统中,我们不能控制不同线程的执行时刻,所以会出现计数值逻辑上不精确的情况。在T2时刻,会话A将计数加1,在T3时刻,会话B读计数时,计数已经加了1,但是却不能查到新加入的记录,因为这条记录在T4时刻才被会话A插入。而使用数据库保存计数就不会出现这种情况。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。