问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

MYSQL COUNT技术问题?

发布网友 发布时间:2022-04-10 22:29

我来回答

2个回答

懂视网 时间:2022-04-11 02:51

2、那为什么走了index_b而不是走了index_c呢?

EXPLAIN结果得知,index_bkey_len为4,index_ckey_len为123,key_len表示索引中使用的字节数,所以肯定使用index_b的数据量更小。

EXPLAIN我们简单得知了没加索引会比加了索引的查询慢了很多,那么都加了索引的情况下会是怎么样的呢?其实是mysql对count()、count(1)、count(id)、count(b)、count(c)的判断各不相同导致的。注:取值和不取值会影响执行速度,因为取值会对数据行进度解析以得到想要的字段。

count(*)
InnoDB遍历整张表,但不取值,count(*)肯定不为空,按行累加就行了。

count(1)
InnoDB遍历整张表,但不取值,server层对于每一行数据返回1,判断1不可能空,按行累加。

count(id)
InnoDB遍历整张表,把每一行的id取出来返回给server层,server层判断不可能为空,按行累加。

count(不可为空字段)
InnoDB遍历整张表,把每一行的这个字段取出来返回给server层,server层判断不可能为空,按行累加。

count(可空字段)
InnoDB遍历整张表,把每一行的这个字段取出来返回给server层,server层判断是不是为空,不为空的按行累加。

count(判断 or null)

假设存在一张子任务表,表主要信息如下:

CREATE TABLE `app_task_child` (
 `task_child_id` varchar(40) NOT NULL,
 `status` int(11) NOT NULL DEFAULT '1' COMMENT '1.待提交;2.审核中;3.已提交;4.已归档;',
 `task_id` varchar(40) DEFAULT NULL COMMENT '母任务',
 PRIMARY KEY (`task_child_id`),
 KEY `FK6m...` (`task_id`),
 CONSTRAINT `FK6m...` FOREIGN KEY (`task_id`) REFERENCES `app_task` (`task_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

现在有一个需求:统计出各任务下的子任务数、已归档数、审核中数的数据。

SELECT
 t.task_id AS taskId,
 count(t.task_child_id) AS taskChildNum,
 count(t.STATUS = 4) AS ongoingNum,
 count(t.STATUS = 2) AS archiveNum
FROM
 app_task_child t
GROUP BY
 t.task_id

技术图片

上面的SQL会查询出图一的数据来,这数据一看就知道不对,已归档数和审核中的数量肯定错了。文章上面大概有说到一个意思:count计算的是除了NULL值,其他数据都会加1,例如0或false也都是会加数量1
t.STATUS = ?判断为false或true,所以count总为加1,导致结果总跟子任务数是一样的。那么就需要想办法当为false时把结果置为NULL。例如有下面两种方法都能得到正确的结果:

-- 方法一
SELECT SQL_NO_CACHE
 t.task_id AS taskId,
 count(t.task_child_id) AS taskChildNum,
 count(IF(t. STATUS = 4, true, NULL)) AS ongoingNum,
 count(IF(t. STATUS = 2, true, NULL)) AS archiveNum
FROM
 app_task_child t
GROUP BY
 t.task_id
-- 方法二
SELECT
 t.task_id AS taskId,
 count(t.task_child_id) AS taskChildNum,
 count(t.STATUS = 4 or NULL) AS ongoingNum,
 count(t.STATUS = 2 or NULL) AS archiveNum
FROM
 app_task_child t
GROUP BY
 t.task_id

方法一的不难理解,这里不进行说明。
方法二(判断 or NULL)可以理解为当判断为0时,会走or后面的表达式,当判断为1时,不走or后面的表达式。判断为1的直接count为1,判断为0时进行NULL的表达式判断,而且0 or NULL为NULL。
在mysql中的or和and判断不像java那样,更像是JavaScript这种弱类型语言的判断,可以把NULL直接进行判断。例如下图中的判断结果
技术图片

count(判断 or null)性能怎么样?

对面上的表进行加status索引。

ALTER TABLE `app_task_child`
ADD INDEX `index_status` (`status`) USING BTREE ;

执行sql

-- 写法一
EXPLAIN SELECT
 t.task_id AS taskId,
 count(t.task_child_id) AS taskChildNum,
 count(t.STATUS = 2 or null) AS archiveNum
FROM
 app_task_child t
GROUP BY
 t.task_id;

结果为:

... type possible_keys key key_len ref rows filtered Extra
... index FK6m... FK6m... 123 39 100

执行sql

-- 写法二
EXPLAIN SELECT
 t.task_id AS taskId,
 count(t.task_child_id) AS taskChildNum,
 count(*) AS archiveNum
FROM
 app_task_child t
where t.status = 2
GROUP BY
 t.task_id;

结果为:

... type possible_keys key key_len ref rows filtered Extra
... ref FK6m...,index_status index_status 123 const 1 100 Using index condition; Using temporary; Using filesort

就只单单从type字段一个为ref一个为index就可得知写法二性能完爆写法一(可以参考别人的文章)
。那么为什么上面不用写法二呢?实际开发中统计的往往不只统计一个num,可能会统计八九个。所以如果使用写法二,需要写八九个SQL去执行,而写法一只需要一条SQL搞定。还有就是这时写法二花费在数据库连接上的损耗加起来往往是比写法一性能更差些。

如果不在status字段上加索引,EXPLAIN比较出来的结果也是方法二性能稍微好一点,这点大家可以自己试一下

MySQL里的COUNT

标签:写法   auto   全表扫描   href   view   重复   很多   -o   rip   

热心网友 时间:2022-04-10 23:59

用处不一样的
count是用来统计SQL里符合某项条件的列数的数量,比如论坛某板块的发帖数,并不需要真的获取该板块所有的发帖的行
而mysql_num_rows是用来获取mysql_query的列数,一般用来判断是否为0,不为0的话mysql_fetch_array
mysql_affected_rows则是用来统计delete,update操作后影响的数量
要获取数字,而不是获取行的话,无所谓几万数据的,就算几行数据,也是count比mysql_num_rows高,到了后期,数据大的时候,应该考虑使用单独的表作为统计
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
减罪的读音减罪的读音是什么 减的拼音? 减的反义词 5种开红色花朵的植物有哪些 怎么查衣服是什么牌子 ...一件连衣裙就要1080元 ,你怎么看?_百度知 ... ...的衣服比较难?这些时尚的淘宝店铺你知道吗?_百度知 ... 比尔布莱森被人们称为什么 三星空气净化器怎么样 ? 三星ax7000空气净化器 求助节目串词 关于歌曲的和声 “广岛之恋”这首歌,用吉他弹唱怎样进行转调? 对照《中学生日常行为规范》做自我书面总结,不少于500字 回忆在遵守中学生行为规范方面,有哪些给你留下深刻印象的经历,并谈谈体会? 2019个人社会保险缴费价格 江阴地区自由职业缴社保费是多少2019年 江阴社保缴费基数2019 江阴社保2019年2019年的缴费基数和缴费比例各是多少 2019年江阴个人交社保 江阴市市社保缴费基数 江阴市个人缴纳社保医保一个月多少钱? 2019年7月江阴市城镇职工基本养老保险缴费基数 2019江阴社保缴费比例 怎样设置笔记本电脑,可以让它长时间不动的情况下不会自动待机? 2019年江阴自己交社保要多少钱 2019年江阴社保基数 兴业银行星座信用卡账单是默认发到邮箱的吗? 兴业信用卡邮箱格式怎么填 芦荟酒中有沉淀物属于正常吗? 热收缩包装机的红外线对人体的危害有哪些 苹果手机钱包绑定银行卡消费后怎么开发票 快手开发票去哪报销 充话费的发票怎么打啊,我要报销的? 假如你成立一个羽毛球俱乐部,你如何建立渠道,实现经营良性发展? 求 羽毛球场馆市场营销方案 请问,想开一家羽毛球俱乐部都需要做那些市场调查和准备???多谢了 我想加入学校团委的文体部,但是要写一篇“羽毛球俱乐部计划”.不明白什么意思?求一篇羽毛球俱乐部计划参 如何经营羽毛球场馆 兔子的尾巴歇后语是什么 怎么组建羽毛球俱乐部,有没有什么章程? 怎么组织羽毛球活动,请教,谢谢大家 兔子的尾巴一一歇后语是什么? 求一份创办羽毛球协会的方案大神们帮帮忙 兔子的尾巴下一句歇后语是什么 兔子尾巴的歇后语是什么? 兔子的尾巴歇后语下一句歇后语是什么 ems昨天下午从广东发货到北京。几天能到 羽毛球俱乐部管理细则 歇后语兔子尾巴下一句是什么