本文旨在介绍COUNT(*),COUNT(1),COUNT(col)三者之间区别和使用索引的情况,count() 函数是用来统计行数用的,以下内容均是个人实践模拟结果,仅供参考;
阿里规范中详细描述了三者之间的区别,验证下:
## 建表
CREATE TABLE t_user (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(50) NULL COMMENT '用户名',
`mobile` varchar(50) NULL COMMENT '手机号',
`address` varchar(255) NULL COMMENT '地址',
PRIMARY KEY (`id`),
UNIQUE INDEX `index_id`(`id`) USING BTREE COMMENT '主键索引'
);
##创建存储过程,向表中插入10万条数据
CREATE PROCEDURE `insert_user`()
BEGIN
DECLARE i INT DEFAULT 1;
START TRANSACTION;
WHILE i <= 100000 DO
INSERT t_user (name,mobile,address) VALUES (CONCAT('maker_', i),CONCAT('1530000111', i),CONCAT('上海市浦东新区_', i));
SET i = i + 1;
END WHILE;
COMMIT;
END;
## 执行存储过程
CALL insert_user();
COUNT * 与 COUNT(1) 写法
t_user 表中的10万条数据,没有字段为null的, 分别执行count(*) 和 count(1), 二者结果都是10万条
将其中的部分数据中name字段更新为null,再验证结果
##创建存储过程,将表中前10000条数据中的name字段设置为null
CREATE PROCEDURE `update_user`()
BEGIN
DECLARE i INT DEFAULT 1;
START TRANSACTION;
WHILE i <= 10000 DO
UPDATE t_user set name = null where id = i;
SET i = i + 1;
END WHILE;
COMMIT;
END;
## 执行存储过程
CALL update_user();
再次分别执行count(*) 和count(1), 结果依然都是10万条数据
所以,count(*) 和 count(1) 在统计行数上是没有区别的,都是统计表中的总行数,不区分字段是否有null
COUNT(col) 写法
同样,t_user 表中的10万条数据,且name字段有10000行是null,执行count(name)来统计行数
结果显示9万条数据,再恢复name字段都有值,不为null,再次执行count(name)来统计行数
结果是10万条数据,所以count(col) 只能统计字段不为null的行,字段为null的行会被过滤
COUNT(DISTINCT col1, col2) 写法
DISTINCT 意思是去重,恢复t_user表数据,name和mobile字段全部不为null,执行count(DISTINCT name, mobile)语句
因为name和mobile字段数据均不相同,所以执行结果是10万条;将mobile字段更新1万条数据为null,name不变,再次执行count(DISTINCT name, mobile)语句
##创建存储过程,将表中前10000条数据中的mobile字段设置为null
CREATE PROCEDURE `update_user_mobile`()
BEGIN
DECLARE i INT DEFAULT 1;
START TRANSACTION;
WHILE i <= 10000 DO
UPDATE t_user set mobile= null where id = i;
SET i = i + 1;
END WHILE;
COMMIT;
END;
## 执行存储过程
CALL update_user_mobile();
结果是9万条,所以DISTINCT去重,会过滤字段为null的行
NPE
NPE(NullPointerException): 空指针异常,当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL;
将t_user表中的mobile字段全部设置为null,分别执行count(mobile)和sum(mobile)语句
假如此时程序代码需要sum函数计算的结果来处理业务逻辑,此时返回了NULL,如果程序未判空操作,那么就会报空指针异常,因此使用 sum()时需注意 NPE 问题。
使用IFNULL函数可解决NPE问题,如果sum结果是NULL,就给个默认值0,可避免NPE问题