关于sql count(列名)、count(常量)、count(*)之间的区别

 更新时间:2023年08月29日 09:00:45   作者:紫金小飞侠  
这篇文章主要介绍了关于sql count(列名)、count(常量)、count(*)之间的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

COUNT(列名)、COUNT(常量)和COUNT(*)之间的区别

COUNT( * )和COUNT(1) :在InnoDB中COUNT(*)和COUNT(1)实现上没有区别,而且效率一样,统计结果中,会包含值为NULL的行数COUNT(字段): 需要进行字段的非NULL判断,所以效率会低一些。

因为COUNT( * )是SQL92定义的标准统计行数的语法,并且效率高,所以没有某个字段不为null 的统计行数需求请直接使用COUNT( * )查询表的行数!

COUNT(id)和COUNT()以外,还可以使用COUNT(常量)(如COUNT(1))来统计行数,那么这三条SQL语句有什么区别呢?

到底哪种效率更高呢?

为什么《阿里巴巴Java开发手册》中强制要求不让使用 COUNT(列名)或 COUNT(常量)来替代 COUNT()呢?

在这里插入图片描述

1、COUNT(列名) ,返回SELECT语句检索的行中expr的值不为NULL的数量。结果是一个BIGINT值。

2、但是,值得注意的是,COUNT( * ) 和count(1)的统计结果中,会包含值为NULL的行数。

那么列名、 常量 和 *这三个条件中,常量 是一个固定值,肯定不为NULL。*可以理解为查询整行,所以肯定也不为NULL,那么就只有列名的查询结果有可能是NULL了。

所以, COUNT(常量) 和 COUNT( * )表示的是直接查询符合条件的数据库表的行数。而COUNT(列名)表示的是查询符合条件的列的值不为NULL的行数。

COUNT(*)是SQL92定义的标准统计行数的语法,因为他是标准语法,所以MySQL数据库对他进行过很多优化。

COUNT(*)和COUNT(1)

COUNT(*)和COUNT(1)这二者到底有没有区别,网上的说法众说纷纭。

有的说COUNT(*)执行时会转换成COUNT(1),所以COUNT(1)少了转换步骤,所以更快。

还有的说,因为MySQL针对COUNT()做了特殊优化,所以COUNT()更快。

那么,到底哪种说法是对的呢?

看下MySQL官方文档是怎么说的:

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

画重点:

same way , no performance difference。

所以,对于COUNT(1)和COUNT(*),MySQL的优化是完全一样的,根本不存在谁比谁快!

COUNT( * )和COUNT(字段)

COUNT(字段),他的查询就比较简单粗暴了,就是进行全表扫描,然后判断指定字段的值是不是为NULL,不为NULL则累加。

相比COUNT(),COUNT(字段)多了一个步骤就是判断所查询的字段是否为NULL,所以他的性能要比COUNT()慢。

COUNT(*)的优化

MySQL中比较常用的执行引擎就是InnoDB和MyISAM。

MyISAM

不包含WHERE或GROUP BY等条件

MyISAM不支持事务,MyISAM中的锁是表级锁;而InnoDB支持事务,并且支持行级锁。

因为MyISAM的锁是表级锁,所以同一张表上面的操作需要串行进行,所以,MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来,如果从一张表中使用COUNT(*)进行查询的时候,可以直接返回这个记录下来的数值就可以了,当然,前提是不能有where条件。

MyISAM之所以可以把表中的总行数记录下来供COUNT(*)查询使用,那是因为MyISAM数据库是表级锁,不会有并发的数据库行数修改,所以查询得到的行数是准确的。

InnoDB

不包含WHERE或GROUP BY等条件

InnoDB来说,就不能做这种缓存操作了,因为InnoDB支持事务,其中大部分操作都是行级锁,所以可能表的行数可能会被并发修改,那么缓存记录下来的总行数就不准确了。

InnoDB中索引分为主键索引和非主键索引主键引的叶子节点中保存的是整行记录,而非主键索引的叶子节点中保存的是该行记录的主键的值。

所以,相比之下,非主键索引要比主键索引小很多,所以MySQL会优先选择最小的非主键索引来扫表。所以,当我们建表的时候,除了主键索引以外,创建一个非主键索引还是有必要的。

count(*)、count(列名)、count(常量)的理解

内容来之阿里巴巴的开发手册:

1.  【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的

标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

2.  【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

3.  【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果 为 NULL,因此使用 sum()时需注意 NPE 问题。

正例:使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL(SUM(column), 0) FROM table;

4.  【强制】使用 ISNULL()来判断是否为 NULL 值。

说明:NULL 与任何值的直接比较都为 NULL。

1) NULL<>NULL 的返回结果是 NULL,而不是 false。

2) NULL=NULL 的返回结果是 NULL,而不是 true。

3) NULL<>1 的返回结果是 NULL,而不是 true。

如何在同一个查询中统计同,一个列的不同值的数量,以减少查询的语句量。

例如:

通过一个查询返回各种不同颜色的商品数量 。

select count(color='blue' or color='red') from items; (不满足条件,因为无法区分不同颜色的商品数量)
select count(*) from items where color = 'blue' and color = 'red';(不满足条件,颜色的条件是互斥的)

下面为满足条件的例子:

select sum(if(color = 'blue', 1, 0)) as blue, sum(if(color = 'red', 1, 0)) as red from items;
select count(color = 'blue' or NULL) as blue, count(color = 'red' or NULL) as red from items;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mysql索引失效的常见九种原因图文详解

    mysql索引失效的常见九种原因图文详解

    索引失效这个问题的前提应该是建立了索引,却没有使用到,或者没有完全使用到,下面这篇文章主要给大家介绍了关于mysql索引失效的常见九种原因的相关资料,需要的朋友可以参考下
    2022-06-06
  • MySQL中CONCAT和GROUP_CONCAT方法的区别详解

    MySQL中CONCAT和GROUP_CONCAT方法的区别详解

    本文主要介绍了MySQL中CONCAT和GROUP_CONCAT方法的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 在MySQL中生成随机密码的方法

    在MySQL中生成随机密码的方法

    这篇文章主要介绍了在MySQL中生成随机密码的方法,作者还给出了密码所对应类型限制的参数表,需要的朋友可以参考下
    2015-05-05
  • mysql语法时采用了双引号““的错误问题

    mysql语法时采用了双引号““的错误问题

    错误原因:使用双引号定义表名和列名导致MySQL报错,应使用反引号,修改方案:将双引号改为反引号,避免语法冲突,总结:在MySQL中,正确使用反引号引用标识符,确保SQL语句符合MySQL语法规则
    2024-10-10
  • 分组查询GROUP BY的使用与SQL执行顺序的讲解

    分组查询GROUP BY的使用与SQL执行顺序的讲解

    今天小编就为大家分享一篇关于分组查询GROUP BY的使用与SQL执行顺序的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • 一篇文章掌握MySQL的索引查询优化技巧

    一篇文章掌握MySQL的索引查询优化技巧

    这篇文章主要给大家介绍了关于如何通过一篇文章掌握MySQL的索引查询优化技巧,文中通过示例代码介绍的非常详细,对大家的学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • MySQL远程连接丢失问题解决方法(Lost connection to MySQL server)

    MySQL远程连接丢失问题解决方法(Lost connection to MySQL server)

    这篇文章主要介绍了MySQL远程连接丢失问题解决方法,Mysql错误Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0解决方法,需要的朋友可以参考下
    2014-06-06
  • windows 64位下MySQL 8.0.15安装教程图文详解

    windows 64位下MySQL 8.0.15安装教程图文详解

    本文通过图文并茂的形式给大家介绍了MySQL 8.0.15安装教程(windows 64位),非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • Mysql如何通过binlog日志恢复数据详解

    Mysql如何通过binlog日志恢复数据详解

    binlog日志用于记录所有更新了数据或者已经潜在更新了数据的所有语句,下面这篇文章主要给大家介绍了关于Mysql如何通过binlog日志恢复数据的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • Mysql中between...and引起的索引失效问题及解决

    Mysql中between...and引起的索引失效问题及解决

    这篇文章主要介绍了Mysql中between...and引起的索引失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07

最新评论