mysql-count(14)

1,不同的引擎有不同的实现方式。myisam直接存在磁盘上,可以直接读取。innodb需要一行行读,再进行累计。

2,innodb因为mvcc(多版本并发控制)的原因,同一时刻不同回话查询的数据可能不一致,

3,show table status可以显示表行数,但是不准确。

4,所以如何计数呢:一是使用缓存,插入一行数据,key就加一,删除就减一,但是redis可能因为重启导致存在丢失更新情况,但即使redis正常工作也会出现数据不准确的问题:因为redis跟db无法支持分布式事务,所以在写的两次操作的中间环节进来一个读线程,无论先读db还是先读redis都可能会出现不准确的问题。

                                 二是使用数据库另一张表进行计数。依靠的是事务之前的隔离性。更新记录数与添加新纪录在一个事务中,如果未提交事务,其中的操作对外面的事务是不可见的。注意代码中的顺序,要先添加新记录,再更新记录数,因为更新记录数会触发行锁,只有在事务提交的时候才会释放行锁,如果放在程序最后,会大大提高并发度。

5,count的几种方式的效率比较。count(*)~=count(1)>count(主键)>count(某一个字段)

 

实践:

同步软文数据时,使用Hedisql终端显示的记录数与xmb的总记录数不相等。通过在程序中埋点debug发现实际数据表中记录数是与xmb返回的总数量是一致的。

出现这种现象的原因:Hedisql终端显示的记录数是通过show table status 命令,获取到rows字段进行显示的,但是这个命令统计的记录数是不准确的

(因为此命令是通过采样统计的方式进行计算行数的,为什么采样:因为一行行统计太耗费性能。);为什么Myisam引擎可以精确显示无where条件下的总记录数,

而innoDb不行,这是因为innoDb采用MVCC机制下,即使是同一时刻,应该返回多少条数据也是不确定的。所以为了精确获取总行数,只能使用count,但是因为count会遍历全表,

所以效率比较低。count的效率比较:count(*)~=count(1)>count(主键)>count(某一个字段);如果在业务中,不想使用count计算总行数,极致优化效率可以新建记数表通过一致性事务解决。

 

posted @ 2019-10-14 15:01  梦飞翔up  阅读(162)  评论(0编辑  收藏  举报