详解 MySQL中count函数的正确使用方法

1. 描述

在MySQL中,当我们需要获取某张表中的总行数时,一般会选择使用下面的语句

select count(*) from table;

其实count函数中除了*还可以放其他参数,比如常数、主键id、字段,那么它们有什么区别?各自效率如何?我们应该使用哪种方式来获取表的行数呢?

当搞清楚count函数的运行原理后,相信上面几个问题的答案就会了然于胸。

2. 表结构

为了解决上述的问题,我创建了一张 user 表,它有两个字段:主键id和name,后者可以为null,建表语句如下。

CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
 `name` varchar(255) DEFAULT NULL COMMENT '姓名',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在该表中共有6000000条数据,前1000000条数据行的name字段为空,其余数据行name=id,使用存储过程造测试数据的代码如下

-- 使用存储过程造测试数据
delimiter;;
create procedure idata()
begin
 declare i int;
 set i=1;
 while(i<=6000000)do
  insert into user values(i, i);
  set i=i+1;
 end while;
end;;
delimiter;
call idata();
-- 将前1000000条数据的name字段置为null
update user set name=null where id<1000000;

3. 执行 SQL 语句及结果

为了区分count函数不同参数的区别,主要从执行时间和扫描行数这两方面来描述SQL的执行效率,同时还会从返回结果来描述`count函数的特性。

  • *符号 —— select count(*) from user;
  • 常数—— select count(1) from user;
  • 非空字段—— select count(id) from user;
  • 可为空的字段—— select count(name) from user;

3.1 *符号

mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 6000000 |
+----------+
1 row in set (0.76 sec)

遍历全表,不取值(优化后,必定不是null,不取值),累加计数,最终返回结果。

3.2 常数

mysql> select count(1) from user;
+----------+
| count(1) |
+----------+
| 6000000 |
+----------+
1 row in set (0.76 sec)

遍历全表,一行行取数据,将每一行赋值为1,判断到该字段不可为空,累加计数,最终返回结果。

3.3 非空字段

mysql> select count(id) from user;
+-----------+
| count(id) |
+-----------+
|  6000000 |
+-----------+
1 row in set (0.85 sec)

遍历全表,一行行取数据(会选择最小的索引树来遍历,所以比相同情况下的count字段效率更高),取每行的主键id,判断到该字段不可为空,累加计数,最终返回结果。

3.4 可为空的字段

mysql> select count(name) from user;
+-------------+
| count(name) |
+-------------+
|   5900001 |
+-------------+
1 row in set (0.93 sec)
  • 若字段定义不为空:遍历全表,一行行取数据,取每行的该字段,判断到该字段不可为空,累加计数,最终返回结果。
  • 若字段定义可为空:遍历全表,一行行取数据,取每行的该字段,判断到该字段可能是null,然后再判断该字段的值是否为null,不为null才累加计数,最终返回结果。
  • 若该字段没有索引,将遍历主键索引树。

4. 执行结果分析

4.1 结果集

首先从结果集的角度来看,前三条 SQL 语句的目的是一样的——返回的是所有行数,而 count 函数的参数是普通字段且字段默认为 null 的时候,它返回的是该字段不为 null 的行数。

4.2 执行时间

从执行时间上来看的话,效率大致是count(可为空的字段) < count(非空字段) < count(常数) < count(*)

5. 总结

count是一个聚合函数,对于返回的结果集,一行行地判断,如果count函数的参数不是NULL,累计值就加1,否则不加。最后返回累计值。

  • count(*)速度最快的原因是它不会在计数的时候去取每行数据值
  • count(1)count(*)稍慢的原因是它会取每个数据行并赋值为1
  • count(非空字段)count(1)稍慢的原因是它会从每个数据行中取出主键 id
  • count(可为空的字段)最慢的原因是它可能需要判断每个数据行中的改字段是否为 null

所以,最好还是用count(*)。

以上就是详解 MySQL中count函数的正确使用方法的详细内容,更多关于MySQL count函数的资料请关注我们其它相关文章!

(0)

相关推荐

  • MYSQL中统计查询结果总行数的便捷方法省去count(*)

    MYSQL的关键词 : SQL_CALC_FOUND_ROWS 查看手册后发现此关键词的作用是在查询时统计满足过滤条件后的结果的总数(不受 Limit 的限制) 例如: 复制代码 代码如下: SELECT SQL_CALC_FOUND_ROWS tid FROM cdb_threads WHERE fid=14 LIMIT 1,10; 假设满足条件的有1000条,这里返回10条. 立即使用 复制代码 代码如下: SELECT found_rows() AS rowcount; 则返回的 rowc

  • MySQL中聚合函数count的使用和性能优化技巧

    本文的环境是Windows 10,MySQL版本是5.7.12-log 一. 基本使用 count的基本作用是有两个: 统计某个列的数据的数量: 统计结果集的行数: 用来获取满足条件的数据的数量.但是其中有一些与使用中印象不同的情况,比如当count作用一列.多列.以及使用*来表达整行产生的效果是不同的. 示例表如下: CREATE TABLE `NewTable` ( `id` int(11) NULL DEFAULT NULL , `name` varchar(30) NULL DEFAUL

  • MySQL中无过滤条件的count详解

    count(*) 实现 1.MyISAM:将表的总行数存放在磁盘上,针对无过滤条件的查询可以直接返回 如果有过滤条件的count(*),MyISAM也不能很快返回 2.InnoDB:从存储引擎一行行地读出数据,然后累加计数 由于MVCC,在同一时刻,InnoDB应该返回多少行是不确定 样例 假设表t有10000条记录 session A session B session C BEGIN; SELECT COUNT(*) FROM t;(返回10000) INSERT INTO t;(插入一行)

  • MySQL里的found_row()与row_count()的解释及用法

    出处:mysqlpub.com MySQL中有两个函数来计算上一条语句影响了多少行,不同于SqlServer/Oracle,不要因为此方面的差异而引起功能问题: 1,判断Select得到的行数用found_rows()函数进行判断. 2,判断Update或Delete影响的行数用row_count()函数进行判断,这里需要注意,如果Update前后的值一样,row_count则为0,而不像SqlServer里的@@rowcount或Oracle里的rowcount,只要update到行,影响的行

  • mysql中count(), group by, order by使用详解

    最近做IM的时候遇到一个问题,同时用到了这三个关键字.就是查询一个人的离线消息详情,我们服务端返回给客户端显示的这个详情包括了三个内容,第一个要求列出离线这段时间哪些人或者群给你发了消息,第二个这其中的某个人或者群发了多少条离线消息,第三个拿出最新的一条显示出来.很明显,group by分组哪些人或者群给你发了离线消息,count()得到离线消息数量,order by时间来排序拿出最新的消息. select count(1) as cnt, msg_data from t_im_chat_off

  • MySQL中count(*)、count(1)和count(col)的区别汇总

    前言 count函数是用来统计表中或数组中记录的一个函数,count(*) 它返回检索行的数目, 不论其是否包含 NULL值.最近感觉大家都在讨论count的区别,那么我也写下吧:欢迎留言讨论,话不多说了,来一起看看详细的介绍吧. 1.表结构: dba_jingjing@3306>[rds_test]>CREATE TABLE `test_count` ( -> `c1` varchar(10) DEFAULT NULL, -> `c2` varchar(10) DEFAULT N

  • 详细解读MySQL中COUNT函数的用法

    MySQL的COUNT函数是最简单的功能,非常有用的计算,预计由一个SELECT语句返回的记录数. 要了解COUNT函数考虑的EMPLOYEE_TBL的的表具有以下记录: mysql> SELECT * FROM employee_tbl; +------+------+------------+--------------------+ | id | name | work_date | daily_typing_pages | +------+------+------------+----

  • MySQL中distinct和count(*)的使用方法比较

    首先对于MySQL的DISTINCT的关键字的一些用法: 1.在count 不重复的记录的时候能用到,比如SELECT COUNT( DISTINCT id ) FROM tablename:就是计算talbebname表中id不同的记录有多少条. 2,在需要返回记录不同的id的具体值的时候可以用,比如SELECT DISTINCT id FROM tablename:返回talbebname表中不同的id的具体的值. 3.上面的情况2对于需要返回mysql表中2列以上的结果时会有歧义,比如SE

  • mysql count详解及函数实例代码

    mysql count详解 count函数是用来统计表中或数组中记录的一个函数,下面我来介绍在mysql中count函数用法. count(*) 它返回检索行的数目, 不论其是否包含 NULL值. SELECT 从一个表中检索,而不检索其它的列,并且没有 WHERE子句时, COUNT(*)被优化到最快的返回速度. 例如: mysql> SELECT COUNT(*) FROM student; COUNT(DISTINCT 字段)这个优化仅适用于 MyISAM表, 原因是这些表类型会储存一个函

  • mysql count提高方法总结

    mysql想必很多程序猿都是不陌生的.很多人在纠结count的用法,怎么样才能查询效果最好.今天来谈谈小编的一些看法,仅供参考. 1.咱们先准备建一个表,并准备好测试数据方便后续步骤测试 以InnoDB引擎表为例 建表语句如下 CREATE TABLE test.test ( a VARCHAR(50) NOT NULL COMMENT 'ddfdf', b VARCHAR(15) NOT NULL COMMENT 'fds', c VARCHAR(20) NOT NULL COMMENT 'a

  • 浅谈MySQL 统计行数的 count

    MySQL count() 函数我们并不陌生,用来统计每张表的行数.但如果你的表越来越大,且是 InnoDB 引擎的话,会发现计算的速度会越来越慢.在这篇文章里,会先介绍 count() 实现的原理及原因,然后是 count 不同用法的性能分析,最后给出需要频繁改变并需要统计表行数的解决方案. Count() 的实现 InnoDB 和 MyISAM 是 MySQL 常用的数据引擎,由于两者实现的不同,导致 count() 操作计算的效率也不同. 对于 MyISAM 来说,它把每个表的总行数都存在

随机推荐