问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MySQL count(*/column)查询优化

创作时间:
作者:
@小白创作中心

MySQL count(*/column)查询优化

引用
CSDN
1.
https://blog.csdn.net/frostlulu/article/details/137121186

在数据库开发和维护过程中,优化查询性能是一个永恒的话题。本文将深入探讨MySQL中count函数的使用技巧,包括count(*)和count(column)的区别,以及如何通过优化查询来提升性能。这些技巧对于数据库开发者和DBA来说具有很高的参考价值。

一、count()的含义

count()用于统计符合条件的记录总数,但其有2种用法:count(*)和count(column)

  • count(*) 统计记录的总数
  • count(column) 统计column列不为空的记录总数

这里的概念可能和部分人的理解有些偏差,在SQL中“”通常代表所有列,SQL会通过查询数据字典来将其解析为所有列名,而count()并不会这样做,它会是直接统计数量。而count(column)只有在column列不为空的情况下才与count()的查询结果相同,因此如果你想统计总记录数,那么直接使用count(),count(column)的结果可能会与你想的不同。

示例:count(*)和count(column)的区别

create table test(
id int primary key auto_increment,
name varchar(32)
);
insert into test values(null, 'Vincent'), (null, null);
select * from test;

表中共2条记录,其中id为2的name是一个空值,查询count(*)和count(name)观察区别:

select count(*), count(name) from test;

二、count()的应用技巧

由于count()是一个聚合函数,因此它在统计时会扫描符合条件的所有记录,如果我们需要统计多项汇总数据,常规的SQL会一次次的扫描结果集,每次统计出一个结果,而利用一些技巧,我们可以一次扫描统计出多个汇总数据。

2.1 同时统计多列

首先改造一下测试数据,假设这是一张销售明细表,新增产品和价格列:

alter table test add product varchar(32), add price decimal(10,2);
truncate table test;
insert into test values(null,'Vincent', 'Table', 100),(null,'Vincent', 'Chair', 50),(null,'Vincent', 'Chair', 50),(null,'Victor', 'Table', 100),(null,'Victor', 'Chair', 50),(null,'Victor', 'Chair', 50),(null,'Victor', 'Chair', 50);
select * from test;

假设现在我有下列问题:

  • Vincent卖了几件商品?
  • Victor卖了几件商品?
  • 产品椅子总销量是多少(不分人员)?
  • 所有产品的销售总金额是多少?

由于这几个问题的分组条件都不同,无法用1个group by条件概括。按照常规思路,第1,2个问题应该是count()然后group by name,第三个问题应该是count() where product='Table',最后在全表扫描一次求出sum(price),即总金额:

select name,count(*) from test group by name;
select count(*) from test where product='Chair';
select sum(price) from test;

虽然上面得到了4个问题的答案,但对表查询了3次,假设在生产环境这个表非常大,那么性能必然低下。稍微优化一下,我们可以用一次查询同时回答上面4个问题:

select 
count(name='Vincent' or null) Vincent的销量,
count(name='Victor' or null) Victor的销量,
count(product='Chair' or null) 椅子的总销量,
sum(price) 总销售金额
from test;

这里利用了count(column)不会统计null的特性,将条件转移到count()函数的内部,实现了一次扫描,多个维度统计。

2.2 利用执行计划

当表中的数据特别大,统计时间特别长,而我们需要的结果又不需要很精确时。可以通过执行计划来查看预估的数量,利用这种方式可以在不实际执行查询的结果下快速得到结果:

示例:统计表中某类数据的数量,直接通过执行计划查看,而不实际执行SQL:

explain select count(*) from test;

注意这种方法之适合不需要精确数字的场景,执行计划中的rows是根据统计信息估计出来的,而统计信息本来就是个采样值而且可能已经比较过时了,使用这个方法前可以先执行 analyze table tab_name; 更新一下统计信息。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号