MySQL COUNT函数的使用与优化


Posted in MySQL onMay 10, 2021

COUNT 函数做什么用?

COUNT 是一个专用的函数,通常有两种不同的方式:计算值和数据行。值指的是非空(Non-NULL)表达式(NULL表示值缺失)。如果我们在 COUNT的参数中指定了列名或其他表达式,则 COUNT 函数是计算该表达式拥有值的次数。这让很多人困惑,相当一部分的原因是值和 NULL 的概念是模糊的。

另一种 COUNT 的形式是简单地计算结果集的数据行数。这是在 MySQL 知道 COUNT 函数参数的表达式不可能为 NULL 时的计算方式。最为典型的例子是 COUNT(*),你也许会以为这是展开数据表的全部列的一种替代形式。事实上,它会忽略了全部列而仅仅对数据行数进行记数。

一个经常犯的错误是我们在 COUNT 的参数里指定了列名然后以为是对数据行进行计数。如果你是想获取结果中的行数,你应该一直使用 COUNT(*),这会使得你的查询语句意图更明确并且可以避免性能问题。

MyISAM 的“神奇”之处

一个常见的误解是 MyISAM 对于 COUNT 查询来说会非常快。MyISAM 的 COUNT 查询确实快,但这种快的场景十分有限:COUNT()查询并且没有 WHERE 条件时才能达到这样的效果,而实际这种场景很少见。MySQL 能够对这个语句进行优化的原因是存储引擎总是知道数据表的准确行数。如果 MySQL 知道一个列col不可能为 NULL,它也会将 COUNT(col) 转换为 COUNT()来进行优化。

MyISAM在 COUNT 查询中有 WHERE条件、或其他对值进行计数时 并没有“神奇”之处。相比其他存储引擎可能快也可能慢,这取决于很多其他因素。

简单的COUNT优化

当你想要对数据行的索引覆盖不高的情况,又需要统计所有行数量时可以采用 MyISAM 引擎的 COUNT(*)来进行优化。下面的例子使用了标准的世界数据库去展示查找 ID 大于5的城市数量时的优化力度,你写出的SQL 语句可能如下所示:

SELECT COUNT(*) FROM world.City WHERE ID > 5;

如果使用 SHOW STATUS 检查查询的话会发现扫描了4079行。而如果是采用负向条件查询,并且减去那些 ID 小于等于5的城市数量的话,你会发现可以将扫描结果减少到5行。

SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5;

这个查询会读取更少的行是因为在查询优化阶段将查询转换为了常量,使用 EXPLAIN 可以看到:

 

id select_type table rows Extra
1 PRIMARY City 6 Using where; Using index
2 SUBQUERY NULL NULL Select tables optimized way

一个常见的问题是如何在一个查询语句中完成对同一列的不同值的数量的查询。例如,你想通过一条查询语句查出不同颜色对应的数量。你不能使用诸如 SELECT COUNT(color = 'blue' OR color='red') FROM items来完成查询,因为这样不会区分出不同颜色相应的数量。而你也不能将颜色放入 WHERE 条件中,例如 SELECT COUNT(*) FROM items WHERE color = 'blue' AND color = 'red'由于颜色本身是互斥的,因此可以用下面的方法解决这一问题:

SELECT SUM(IF(color = 'blue', 1, 0)) AS blue, 
SUM(IF(color = 'red', 1, 0)) as red FROM items;

还有一种变通的形式是不是要 SUM,而是 COUNT,只是保证了没有值的表达式的判决表达式是 false:

SELECT COUNT(color = 'blue' OR NULL) as blue,
COUNT(color = 'red' OR NULL) as red FROM items;

使用近似值

有时候并不需要精确的数量,这个时候就可以使用近似值。在 EXPLAIN优化器中给出的估计行数通常可以满足这种场景,此时可以使用 EXPLAIN 来替代真实的查询。

在很多情况下,一个准确的数量与近似值相比低效很多。一个客户曾经要求统计他们网站的活跃用户数量。用户数量被缓存并每隔30分钟更新一次。这本身就不准确,因此使用估计值是可以接受的。这个查询使用了多个 WHERE 条件去保证不会统计非活跃用户或默认用户(拥有特殊的 ID)。移除这些条件,并稍微修改一下 count 操作就可以变得更高效。一个更进一步的优化是移除不必要的 DISTINCT 操作,从而移除掉一次 filesort 操作。优化后的查询速度更快,且返回了几乎准确的结果。

更复杂的优化

通常来说,COUNT查询很难优化,这是因为它通常需要统计很多行(访问很多数据),在 MySQL 中其他可选的办法是使用覆盖索引。如果那还不够的话,可能需要对整个系统应用架构进行调整了。例如考虑统计数据表,或者使用外部的缓存系统(如 Memcached)。我们往往会面临一个类似的两难问题:快速、准确和简单——你只能从中选择两项!

以上就是MySQL COUNT函数的使用与优化的详细内容,更多关于MySQL COUNT的使用与优化的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
教你用eclipse连接mysql数据库
Apr 22 MySQL
MySQL之高可用集群部署及故障切换实现
Apr 22 MySQL
详解MySQL数据库千万级数据查询和存储
May 18 MySQL
MySQL5.7并行复制原理及实现
Jun 03 MySQL
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
Jun 26 MySQL
MySQL如何解决幻读问题
Aug 07 MySQL
详细聊聊MySQL中慢SQL优化的方向
Aug 30 MySQL
MySQL8.0升级的踩坑历险记
Nov 01 MySQL
Arthas排查Kubernetes中应用频繁挂掉重启异常
Feb 28 MySQL
Pycharm远程调试和MySQL数据库授权问题
Mar 18 MySQL
mysql中如何用命令创建联合唯一索引
Apr 20 MySQL
MySQL普通表如何转换成分区表
May 30 MySQL
解读MySQL的客户端和服务端协议
MySQL 重写查询语句的三种策略
May 10 #MySQL
详解MySQL 联合查询优化机制
mysql对于模糊查询like的一些汇总
May 09 #MySQL
MySQL Threads_running飙升与慢查询的相关问题解决
MySQL sql_mode的使用详解
May 08 #MySQL
MySQL 数据丢失排查案例
May 08 #MySQL
You might like
php jquery 实现新闻标签分类与无刷新分页
2009/12/18 PHP
php.ini save_handler 修改不生效的解决办法
2014/07/22 PHP
PHP使用header()输出图片缓存实例
2014/12/09 PHP
php连接odbc数据源并保存与查询数据的方法
2014/12/24 PHP
ext combox 下拉框不出现自动提示,自动选中的解决方法
2010/02/24 Javascript
jquery模拟实现鼠标指针停止运动事件
2016/01/12 Javascript
async/await与promise(nodejs中的异步操作问题)
2017/03/03 NodeJs
详解vscode中vue代码颜色插件
2018/10/11 Javascript
如何实现小程序tab栏下划线动画效果
2019/05/18 Javascript
JS中的一些常用的函数式编程术语
2019/06/15 Javascript
vue实现可移动的悬浮按钮
2021/03/04 Vue.js
python列表去重的二种方法
2014/02/14 Python
python数据结构之二叉树的遍历实例
2014/04/29 Python
解决Python中由于logging模块误用导致的内存泄露
2015/04/23 Python
在Django中进行用户注册和邮箱验证的方法
2016/05/09 Python
python实现求解列表中元素的排列和组合问题
2018/03/15 Python
对DataFrame数据中的重复行,利用groupby累加合并的方法详解
2019/01/30 Python
wxpython多线程防假死与线程间传递消息实例详解
2019/12/13 Python
Python之Class&amp;Object用法详解
2019/12/25 Python
python如何更新包
2020/06/11 Python
css3实例教程 一款纯css3实现的发光屏幕旋转特效
2014/12/07 HTML / CSS
基于 HTML5 Canvas实现 的交互式地铁线路图
2018/03/05 HTML / CSS
Html5实现文件异步上传功能
2017/05/19 HTML / CSS
BIBLOO捷克:购买女装、男装、童装、鞋和配件
2017/01/27 全球购物
一道Delphi上机题
2012/06/04 面试题
护理职业生涯规划书
2014/01/24 职场文书
学习交流会主持词
2014/04/01 职场文书
医学生求职自荐书
2014/06/12 职场文书
竞选大队干部演讲稿
2014/09/11 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
商业用房租赁协议书
2014/10/13 职场文书
2015年党性分析材料
2014/12/19 职场文书
2015年第十五个全民国防教育日宣传活动方案
2015/05/06 职场文书
2015年语文教师工作总结
2015/05/25 职场文书
2019年员工旷工保证书!
2019/06/28 职场文书
Python手拉手教你爬取贝壳房源数据的实战教程
2021/05/21 Python