mysql实战45讲学习笔记--14

14  count(*)这么慢,我该怎么办

       Count()的实现方式
       不同数据引擎,count(
)有不同实现方式
        MyISAM引擎吧一个表的总行数存在磁盘上,因此执行count(*)直接返回这个数,效率高
        InnoDB在执行的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数

       在事务支持,并发能力还是数据安全,InnoDB都优于MyISAMDL。

       InnoDB不跟MyISAM一样,将数字存起来是因为多版本控制(MVCC),InnoDB表“应该返回多少行”也是不确定的。
       InnoDB默认隔离级别是可重复读,多版本并发控制使用mvcc来控制,每一行都需要判断自己是否对这个会话可见,因此Count()只好将数据一行一行读出判断。
       在保证逻辑情况正确的前提下,尽量减少扫描的数据量,是数据库系统设计的通用法则之一。
       使用show table status命令用于显示这个表当前有多少行,但是不准确,误差达到40%-50%
       MyISAM 表虽然 count(
) 很快,但是不支持事务
       show table status 命令虽然返回很快,但是不准确
       InnoDB表直接count(*)遍历全表,虽然结果准确,但是会有性能问题。

       因此有些记录操作总数的情况,我们需要自己计数。
       1.用缓存系统保存计数
       将计数保存在缓存系统中的方式,不仅仅是丢失更新的问题,即使Redis正常工作,这个值还是逻辑上不精确的。
       2.在数据库保存计数
       使用的时候加上事务,这样就能解决计数问题不精确的问题。

       不同的count用法
       Count()是一个聚合函数,对于返回的结果集,一行行的判断,如果count函数的参数不是null,累计值就加一,否则不加,最后返回累计值。
       Count(*),count(主键id),count(1)都表示返回满足条件的结果集的总行数,而count(字段)则表示返回满足条件的数据行里面,参数“字段”部位null的总个数。

       分析性能的时候,记住几个原则
       1.server层要什么就给什么
       2.InnoDB只给必要的值
       3.现在的优化器只优化了count(*)的语义为“取行数”,其他优化没有做

       对于count(主键id)来说,InnoDB引擎会遍历整张表,把每一行的id值都取出来,返回给server层,server取到id后,判断是不可能为空的,就按行累加。
       对于count(1)来说,INnoDB遍历整张表,但不去自,server层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加
       Count(1)就要比count(主键id)快。
       对于count(字段)来说
       1.如果这个字段定义为not null的话,一行行地重记录里面读出这个字段,判断不能为null,按行累加
       2.如果这个字段定义允许为null,那么执行的时候,判断到有可能是null,还会将值取出来再判断一下,不是null再累加。
       Count()是例外,专门做了优化,不去自,count()肯定不是null,按行累加。

  因此,按照效率排序:count(字段)<count(主键id)<count(1)≈count(*)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值