MySQL函数:Count
MySQL是一个流行的关系型数据库管理系统,其中,COUNT最常用的函数之一,它可以帮助用户快速获取某个表或查询的行数。本文将详细介绍COUNT函数的用法和性能对比。
count()
基本用法
COUNT
函数是一个聚合函数,它用于计算一个表或查询中的行数。在MySQL
中,COUNT
函数可以用于任何数据类型的列。
基本语法如下:
SELECT COUNT(column_name) FROM table_name;
其中,column_name
是要计算的列的名称,table_name
是表的名称。在执行COUNT
函数时,它会忽略列值为NULL
的行,因此如果要计算包括NULL
值的行数,则需要使用COUNT(*)
函数:
SELECT COUNT(*) FROM table_name;
我们先来创建user
表使用下
mysql> show create table user;
+-------+---------------------------------+
| user | CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '1',
`age` int(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `nameIndex` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------+
mysql> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 0 | 陈 | 3 |
| 1 | 李 | 12 |
| 2 | 张 | 14 |
| 3 | 陈 | 6 |
| 4 | 李 | 3 |
| 5 | NULL | 7 |
| 7 | 张 | 19 |
+----+------+-----+
7 rows in set (0.06 sec)
mysql> select count(name) from user;
+-------------+
| count(name) |
+-------------+
| 6 |
+-------------+
1 row in set (0.06 sec)
mysql> select count(distinct name) from user;
+----------------------+
| count(distinct name) |
+----------------------+
| 3 |
+----------------------+
1 row in set (0.06 sec)
使用场景
除了简单的计算行数之外,COUNT
函数还可以与其他函数结合使用,以实现更复杂的统计。例如,可以使用GROUP BY
语句将数据分组并计算每个组的行数。示例如下:
SELECT column_name, COUNT(*) FROM table_name GROUP BY column_name;
在上面的查询中,将按照column_name
列中的不同值进行分组,并计算每个组中的行数。结果将返回两列,第一列为不同的column_name
值,第二列为每个组中的行数。
在实际应用中,COUNT
函数可以广泛应用于许多场景中。例如,它可以用于确定某个表或查询是否为空,或者用于计算某个列中的唯一值的数量。此外,它还可以用于统计某个时间段内的记录数量等等。
实现方式
在不同的MySQL
引擎中, count
有不同的实现方式。
-
对于
MyISAM
,表存储了确切的总行数,可以非常快速地访问 -
对于
InnoDB
, 对于返回的结果集,一行行地判断, 把每一行的expr
值都取出来, 返回给server
层。server
层拿到字段后, 判断!= NULL
的, 就按行累加计数,最后返回累计值。
为什么InnoDB不跟MyISAM一样, 也把数字存起来呢?
InnoDB
不保留内部计数表中的行,因为并发事务可能在同时间里“看到”的是不同数量。由于多版本并发控制(MVCC
)的原因, 应该返回多少行也是不确定的。
如果近似行数就足够了,可以使用SHOW TABLE STATUS
,通过索引统计的值采样来估算的。误差可能达到40%到50%;
性能差异
从MySQL 8.0.13
开始,InnoDB
的count
会优先遍历最小普通索引,除非索引或优化器提示 指示优化程序使用不同的索引。如果普通索引不存在,则扫描聚集索引。
count(*)、 count(主键id)、 count(字段)、count(1)
等不同用法的性能, 有哪些差别?
count(*)、count(主键id)、count(1)
表示返回满足条件的结果集的总行数;
count(字段)
则表示返回满足条件的数据行里面, 参数“字段”不为NULL
的总个数。
-
对于
count(主键id)
:InnoDB
会选择占用存储空间最小的那个索引来执行查询, 然后取出每一行ID
,判断是否为空,然后计数累加。 -
对于
count(1)、count(*)
:InnoDB
引擎会使用占用存储空间最小的那个索引来执行查询, 但不取值。把每一行计数累加。 -
对于
count(非索引列)
: 优化器选择全表扫描
- 对于
count(普通索引列)
:选择包含我们指定的列的索引去执行查询,但是当前执行的索引并不一定是最小的。
小结
最后结论是:按照效率排序的话,建议尽量使用count(*)
。
count(1) = count(*) > count(主键id) > count(索引字段) > count(非索引字段)
转载自:https://juejin.cn/post/7212889505371750460