• mysql中count()函数用法:count(1)和count(*)有什么区别?


    count(*)、count(1)、count(字段)都有什么区别?

    在我们的日常开发中,经常会遇到计算一张表的行数的情况,通常情况下我们使用一条select count(*) from t 语句就完事了。但是大家也可能看到count()函数的别的用法,比如count(1)count(字段名),那么他们和count(*)有什么区别呢?count(*)又是如何进行查询得到我们要的数据呢?本文就带大家一一揭晓。


    一、count(*)是如何实现的

    首先我们要知道,在不同的存储引擎中,count(*)的实现是不一样的。以select count(*) from t这条语句来说:

    • 在MyISAM中,由于每个表的总行数会作为一个变量存储在磁盘上,所以执行查询的时候只用返回这个变量的值就好了,查询速度比较快;
    • 而对于我们常用的InnoDB来说,它会一行一行的将数据读取出来,然后对读取的数据进行累计计数,最后得到结果,查询会慢一些;

    这里大家可能就想到了,为什么InnoDB不像MyISAM那样也将总行数存储起来呢?

    注意了,我们这里的读是快照读,对于快照读来说,InnoDB是通过MVCC进行控制的,也就是说我们是可能会读取到历史数据的,因此读取的总行数并不是确定的,当然不能一视同仁的返回同一个值了。

    如果你还不了解MVCC,可以看我的这篇文章:MVCC详解,深入浅出简单易懂_lans_g的博客-CSDN博客_mvcc

    InnoDB的设计者当然也意识到了这个问题,所以他对count(*)操作进行了一定的优化。

    对于上面的这条查询语句来说,无非就是要得到表的总行数嘛,表中的字段值我们并不关心。InnoDB是索引组织表,主键索引树的叶子节点是数据,而普通索引树的叶子节点是主键值。所以,普通索引树比主键索引树小很多。对于count(*)这样的操作,遍历哪个索引树得到的结果逻辑上都是一样的。因此,MySQL优化器会找到最小的那棵索引树来遍历,这样就提高了检索效率。

    count(参数)是一个聚合函数,对于某一个结果集逐行进行判断,如果该行参数不为null,则+1,最后返回累计值。由于count(*)肯定不为null,所以经过优化后,在进行查询时并不会取出字段的值,而是逐行进行累加,有多少行就返回几。


    二、对比count(1)、count(字段名)

    除了count(*),大家可能会看到这样的写法:count(1)。这是什么意思呢?

    对于count(1)来说,InnoDB遍历整张表的时候,同样不会取出字段的值,而是对于返回的每一行后面加一个数字“1”,然后按行累加。是不是和count(*)很类似?事实上,他们的执行效率也是差不多的。

    上文我们说了,count(参数)函数会对参数不为null的行进行计数,因此对于count(字段)来说,会先读取该字段中的值判断不为null后,再累加。


    三、总结一下

    由于count(1)和count(*)并不会取出字段中的值,因此效率是比较高的,如果按照效率排序的话:

    count(字段)

    不过既然count( * )已经优化了这么多,推荐大家使用count(*)就好了。

  • 相关阅读:
    22年多校第三场(F的证明
    机场、公交枢纽定位解决方案
    Unity之ShaderGraph如何实现飘动的红旗
    Spark GraphX 图算法的理解
    HTML介绍——HTML筑基
    如何处理CAN通讯故障
    面试题:Java中为什么只有值传递?
    Elasticsearch 7.6 集群搭建
    浏览器跨域请求
    程序化交易的关键是进场策略和操作纪律
  • 原文地址:https://blog.csdn.net/lans_g/article/details/126544293