刚给一个朋友解决他写的Discuz!插件的问题,说到MySQL的COUNT(*)的效率,发现越说越说不清楚,干脆写下来,分享给大家。
COUNT(*)与COUNT(COL)
网上搜索了下,发现各种说法都有:
比如认为COUNT(COL)比COUNT(*)快的;
认为COUNT(*)比COUNT(COL)快的;
还有朋友很搞笑的说到这个其实是看人品的。
在不加WHERE限制条件的情况下,COUNT(*)与COUNT(COL)基本可以认为是等价的;
但是在有WHERE限制条件的情况下,COUNT(*)会比COUNT(COL)快非常多;
具体的数据参考如下:
mysql> SELECT COUNT(*) FROM cdb_posts where fid = 604;
+------------+
| COUNT(fid) |
+------------+
| 79000 |
+------------+
1 row in set (0.03 sec)
mysql> SELECT COUNT(tid) FROM cdb_posts where fid = 604;
+------------+
| COUNT(tid) |
+------------+
| 79000 |
+------------+
1 row in set (0.33 sec)
mysql> SELECT COUNT(pid) FROM cdb_posts where fid = 604;
+------------+
| COUNT(pid) |
+------------+
| 79000 |
+------------+
1 row in set (0.33 sec)
COUNT(*)通常是对主键进行索引扫描,而COUNT(COL)就不一定了,另外前者是统计表中的所有符合的纪录总数,而后者是计算表中所有符合的COL的纪录数。还有有区别的。
COUNT时的WHERE
这点以前就写过,详细请看《Mysql中count(*),DISTINCT的使用方法和效率研究》:https://kimi.pub/156.html
简单说下,就是COUNT的时候,如果没有WHERE限制的话,MySQL直接返回保存有总的行数
而在有WHERE限制的情况下,总是需要对MySQL进行全表遍历。
优化总结,对于MyISAM表来说:
1.任何情况下SELECT COUNT(*) FROM tablename是最优选择;
2.尽量减少SELECT COUNT(*) FROM tablename WHERE COL = 'value' 这种查询;
3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = 'value' 的出现。
在oracle中count(col)的性能就会好于count(*)
看来数据库中的差异还是挺大的,sql的优化不能一概而论啊。
@LVEYO,
你说错了!oracle中对count是有优化特殊处理的,并不是你想的count(*)就比count(col)差,二者是相同的。你可以使用dbms_xplan查看具体的执行计划,并做个大表试试。
我一般都是select count(1) from tables , 那个1是不存在的字段
你好… 最近想学MYSQL 之前用的是SQL SERVER 2000 然后去载了个PHPMYADMIN 但是配置文件一直出错 打不开 能不能帮忙解决下??
除了考虑效率,还得结合实际情况。
比如,如果要查询的字段可能有null值,而又想排除这条数据,就只能用count(col)了
幸好我一向用select count(*)
其时个人感觉count(*)的确要比别的都快,但是,据我上次测试后发现sum(1)的速度在特定的条件下面要比count(*)快。
@枫叶 具体点呢,什么情况下sum(1)的效率会更好的呢?
“简单说下,就是COUNT的时候,如果没有WHERE限制的话,MySQL直接返回保存有总的行数
而在有WHERE限制的情况下,总是需要对MySQL进行全表遍历。”
只有MyIsam engine适用上面吧?
@guest, 好的,本文是针对MyIsam
1.任何情况下SELECT COUNT(*) FROM tablename是最优选择;
对这点有个凝问
假设表A,有个文本字段,平均每条记录文本大小为200个汉字,表记录条数在50w左右。是否还是SELECT COUNT(*) FROM tablename最优呢?
@guest, 是的,不加WHERE的查询,MySQL直接返回保存有总的行数
COUNT(*)与COUNT(COL)首先在统计的数据上就有不同。COUNT(*)统计的是记录集的记录数,COUNT(COL)返回的是记录集中COL的value不为null的记录数。两者还有有区别的,所以在某些场合是不能彼此替换的。我的理解是这样的http://hi.baidu.com/dearhwj/blog/item/3a45b28de358031ab31bba1b.html,如果有不正确的地方请赐教!
@Daniel Hu, 感谢你的回复,你发的地址,对本文是一个很好的补充:)
在没有索引的情况下count(field)会快很多?
@cevin91, 任何情况下SELECT COUNT(*) FROM tablename是最优选择
不是很同意兄弟的说法.
我测试的结果,是带where条件下,count(pk)比count(*)快些.
学习了,呵呵,用这好几年MYSQL,还真的没有测试过,有时候,我用count(1)的,不知效率又是怎样,找时间测试一下。
大哥 你的总结是错的!!! 误人子弟
@fuck, 对于MyISAM表来说,是这样的啊
什么结论都是有条件的
学习了,以前没有看到过,今天看了以后受到了教育。以前,我总粗略的认为 count(某个字段)会比count(*)快,现在看来不能随便猜想!感谢!
楼主的观点是错误的。我已经验证过啦。误人啊
楼主的观点是错误的。我已经验证过啦。
写的真好,最近在查mysql XXX 效率 的时候都是你的站排在最前面, 记得第一次访问你的站的时候还是在前公司里,两年以前了。
SELECT count(0) FROM TABLE; 你有没有试过比较这种的效率?
gravatar头像没有显示,修改一下吧。
换成国内的就OK了