MySQL count(*/column)查询优化的实现
作者:V1ncent Chen
count()是SQL中一个常用的聚合函数,其被用来统计记录的总数,下面通过几个示例来说明此类查询的注意事项及应用技巧。
一、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; 更新一下统计信息。
到此这篇关于MySQL count(*/column)查询优化的实现的文章就介绍到这了,更多相关MySQL count(*/column)查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!