【Mysql】 count() 慢问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w372426096/article/details/87855925

不同引擎中,count(*)有不同的实现方式

MyISAM:把一个表的总行数存在了磁盘,因此在获取行数时候直接返回,效率高。如果加where条件就不能返回这么快

InnoDB:需要一行行从引擎里面读出来,累计计数,因为事务的支持所以通过MVCC并发控制,读取行数时候据需要一行行的读出来判断。

MySQL优化器会找到最小的那棵树来遍历,在保证逻辑正确的前提下,尽量减少扫描的数据量,是数据库系统设计的通用法则之一。

数据一致性问题目前来说主要分为三类(获取行数)
1.主从不一致
解决办法:半同步复制after_commit,after_sync,MGR(after_prepare)。但是都不能完成满足完全实时一致,由于等待的ack点不同,相对来说一致性的强度是递增.
2.数据库与缓存的不一致
解决办法:读操作直接读缓存,写操作先更新到数据库,淘汰缓存(程序需要保证两个操作的原子性).由于该key的缓存已经清理掉,那么下次读的时候需要先读数据库,在重建缓存.
由于redis是单线程,保证了一个操作的原子性.可以通过设置appendfsync always来保证每次操作都把该操作记录并落盘到aof文件里(不过一般redis该值为everysec),毕竟使用redis的目的不是为了保证acid.还是要根据业务来选择;

把计数放在Redis里面,不能够保证计数和MySQL表里的数据精确一致的原因,是这两个不同的存储构成的系统,不支持分布式事务,无法拿到精确一致的视图。
3.一个事务跨多个节点或者多种数据库(分库分表和银行转账这种例子)
InnoDB引擎支持事务,利用好事务的原子性和隔离性,就可以简化在业务开发时的逻辑。

count(字段值):如果该字段上有null值.每行的行头有一个标记位,标记该行是否为null.所以多了一层判断。相对更耗时


count(主键id):InnoDB会遍历整张表,把每一行的id值取出来,返回给server层,server层拿到id后,判断是不可能为空的,就按行累加


count(1):InnoDB遍历整张表,但不去治,server层对返回的每一行,放一个数字1,判断是不可能为空的,按行累加。

count(*):并不会把全部字段取出来,而是专门做了优化,不取值,*肯定不是null,按行累加。

count(字段)<count(id)<count(1)≈count(*)

猜你喜欢

转载自blog.csdn.net/w372426096/article/details/87855925