count(*)count(1)和 count(col)区别

本文详细探讨了SQL中COUNT(*)、COUNT(1)和COUNT(col)的区别与执行方式,通过实验对比不同场景下这些函数的性能表现,揭示了在有无索引情况下,数据库如何选择最优路径进行统计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 背景

初识SQL,在实习,跑数据中,写了点SQL来检查数据:上面三行是我的,第三个是小姑娘写的

select count(*) from Jzt_jdKuaiche_accountStatement_promotionUnitStatement where startTime='2019-06-01' and platform='all'
select count(*) from Jzt_jdKuaiche_accountStatement_promotionUnitStatement where startTime='2019-06-01' and platform='PC'
select count(*) from Jzt_jdKuaiche_accountStatement_promotionUnitStatement where startTime='2019-06-01' and platform='mobile'`

有点麻烦,参照教程里的例子group by了下~

select platform,startTime,count(1) from Jzt_jdKuaiche_accountStatement_promotionUnitStatement 
where dateType='month' and startTime='2019-06-01' 
GROUP BY platform,startTime order by startTime

对于一个初学者
是在有点困惑:count(*),count(1),count(col)有什么区别?

select platform,startTime,count(*) from Jzt_jdKuaiche_accountStatement_promotionUnitStatement 
where dateType='month' and startTime='2019-06-01' 
GROUP BY platform,startTime order by startTime

我把上面语句里的count(1)改成count(*),执行下来然后并没有发现什么区别~

2. 知识点

先来学习下count():

1、COUNT(*) 函数返回表中的记录数:
语法:

SELECT COUNT(*) FROM table_name

2、COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):
语法:

SELECT COUNT( column_name) FROM table_name

3、COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:
语法:

SELECT COUNT(DISTINCT column_name) FROM table_name

问了问同事,我得到的回答是:在SQL里 * 号代表所有,查询数据量的数量级达到千以上就执行效率就会比count(1)要低。在查询小批量数据,count(*)和count(1)没啥区别。

但是:
count(*)和count(1)具体怎么执行的呢?
count(1)里面1究竟指代什么?
留待慢慢深入~


3. 补充实验

断断续续学习mysql也有一阵了,补充一下对count的理解~
orders表结构如下(测试环境mysql5.7.30,Innodb存储引擎):
在这里插入图片描述
orders表只有PK约束,各字段未建索引
造点数据:

import random

for i in range(1, 10001):
    # "insert into orders(o_id, s_id, f_name, f_price) values(1, 101, 'apple', 5.2)"%()
    # "insert into orders(o_id, s_id, f_name, f_price) values({},{},{},{}".format(o_id,s_id,f_name,f_price);
    # [o_id, s_id, f_name, f_price]
    suppliers = [101, 102, 103, 104, 105]
    fruits = ['apple', 'pear', 'pineapple', 'banana', 'blueberry', 'strawberry', 'orange', 'melon', 'blackberry']

    o_id = i
    s_id = random.choice(suppliers)
    f_name ="\'"+ random.choice(fruits)+"\'"
    f_price = str(random.uniform(1, 20))[:5]

    sql = "insert into orders(o_id, s_id, f_name, f_price) values({},{},{},{});\n".format(o_id, s_id, f_name, f_price);
    print(sql)
    with open("D:/Users/***/Desktop/order.txt", "a") as f_new:
        f_new.write(sql)

一万条数据有点少,count下来时间都很短~

执行计划
在这里插入图片描述
可以看出,该场景中count(*) 和count(1)还有count(pk_index_col)等价,都统计行记录,并且都走PK索引。

加个索引试试~
在这里插入图片描述
就走索引了~
but~
在这里插入图片描述
count(*),count(1)都不走主键索引啦!
原因嘛,细想也很简单:
主键索引也就是聚集索引,聚集索引的BTREE的叶子结点存储的是完整的行记录,而我们新建的name_index也就普通索引,它存储的是带有主键值的行记录,占据空间小,innoDB为了合理使用资源,选择占用空间最小的索引进行统计。
count(*),count(1)有区别吗?
5.7官方文档有句话如下:
在这里插入图片描述
in the same way! count(*),count(1)就是没区别一毛一样了~

4. 结论

所以,我们大概可以得到以下几点:
(1)count(col)和count(*)统计的维度是不一样的:
  count(*)统计表中的记录数;
  count( col )统计表中col列的不为空的记录数;
(2)count( * ) = count(1)≈ count(index_col)具体场景具体讨论;
(3)有索引时,count( * ),count(1)优先选择占用空间最小的索引进行统计;
(4)count(col) 其中col列有索引即走索引,无索引,就全表扫描。

待补充实验:

  1. 行记录存在空值情况
  2. 条件查询统计情况

参考文献:
[1]SQL COUNT() 函数 https://www.w3school.com.cn/sql/sql_func_count.asp
[2]Select count(*)和Count(1)的区别和执行方式 - CareySon - 博客园 https://www.cnblogs.com/CareySon/p/DifferenceBetweenCountStarAndCount1.html
[3]https://zhuanlan.zhihu.com/p/28397595

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值