mysql count(*)、count(1)、count(主键id)、count(字段)的区别

以下讨论是基于InnoDB存储引擎,这也是mysql默认的存储引擎。

count 函数的语义

要想弄清楚count(*)、count(1)、count(主键id)、count(字段)的区别,需要弄清楚count函数的语言,该函数拿到传进来的参数后,会一行一行地遍历结果返回集,如果某行参数不为Null,就累计计数加1,如果某行参数为Null,就跳过。count(字段)就会判断该行的某个字段是否Null来决定累计计数是否加1

分析性能差异时遵守的原则

在分析count(*)、count(1)、count(主键id)、count(字段)的性能区别时,遵守以下几个原则:

  • server层要什么就给什么
  • InnoDB只给必要的值
  • mysql优化器只对count(*)语句做了优化

不同count参数执行过程

count(主键id)

mysql server层执行器调用 count(主键id),InnoDB存储引擎发现server层需要的是主键id。于是,InnoDB会遍历整张表,把每一行的主键id都取出来,返回给server层。server层执行器拿到主键id后,判断其是否为空,不为空,累计计数加1。注意:主键是不允许为空的,所以累计计数一定会加1,这是显而易见的,但是server层还是要判断一下

count(1)

mysql server层执行器调用 count(1),InnoDB存储引擎发现server层需要的是1。于是,InnoDB会遍历整张表,把每一行取出来,但是不取任何值,而是把该行返回给server层。server层对于返回的每一行,放一个数字"1"进去,然后判断1是不是为空,不为空累计计数就加1.注意:server层放一个数字1,1一定是不为空,这是显而易见的,但是server层还是要判断一下1是否为空

count(字段)

mysql server层执行器调用 count(字段),InnoDB存储引擎发现server层需要的是某个字段。于是,InnoDB会遍历整张表,把每一行的目标字段都取出来,返回给server层。server层执行器拿到目标字段后,判断其是否为空,不为空,累计计数加1。注意:如果目标字段在定义的时候不允许为空的话,在用该count(字段)时累计计数一定会加1,这是显而易见的,但是server层还是要判断一下

count(*)

mysql对count()语句做了专门的优化,InnoDB看到是count(*),并不会取值,而是按行累加。应为count()就是按行累计,这是显而易见的。

为什么count(1)、count(主键id),count(非空字段)按行累加是显而易见的,但mysql却没有优化它们?

因为这种专门优化的情况太多了,而且mysql已经优化过count(*)了,你直接使用就行了。

结论

按照效率排序:count(字段)<count(主键id)<count(1)<count(*)。
所以尽量使用count(*)

为什么count(主键id)<count(1)?

因为count(主键id)涉及到解析行数据,拷贝字段。而count(1)直接返回行,所以count(1)效率更快

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值