数据库啊~
-
- 1. 背景
- 2. 知识点
- 3. 补充实验
- 4. 结论
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 randomfor 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]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
推荐阅读
- mybatis|(附源码)计算机毕业设计ssm电影票购票系统
- 数据库|Linux环境Mysql大小写敏感-不生效
- 数据库|MySQL到底大小写敏感还是不敏感?
- 资讯|频繁被吐槽的Java依然很强大!
- 使用P6Spy监控你的SQL输出
- 用Docker安装nginx和vsftpd搭建文件服务器
- 课程设计|SQLServer连接数据库读取中文乱码问题解决
- java|阿里面试官(如何测试接口幂等性())
- DAG 任务调度与 go-streams 结合的应用实践