设为首页 收藏本站
查看: 866|回复: 0

[经验分享] mysql中innodb表的count

[复制链接]

尚未签到

发表于 2018-10-4 12:38:35 | 显示全部楼层 |阅读模式
  其实就一个问题:count(1),count(*),count(主键),count(非主键字段)哪个更快?
  于是建了一张测试表,插入了600多万条记录。表结构如下:
  


  • CREATE TABLE `test` (
  •   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  •   `c1` varchar(10) NOT NULL,
  •   `c2` varchar(10) NOT NULL,
  •   `c3` varchar(10) NOT NULL,
  •   PRIMARY KEY (`id`)
  • ) ENGINE=InnoDB AUTO_INCREMENT=6003060 DEFAULT CHARSET=utf8
  

  看看下面三条sql:


  • 1.select count(1) from test;
  • 2.select count(*) from test;
  • 3.select count(id) from test;
  • 4.select count(c1) from test;
  下面是命令行下的执行情况:
  


  • mysql> select count(1) from test;
  • +----------+
  • | count(1) |
  • +----------+
  • |  6003058 |
  • +----------+
  • 1 row in set (1.74 sec)
  

  


  • mysql> select count(*) from test;
  • +----------+
  • | count(*) |
  • +----------+
  • |  6003058 |
  • +----------+
  • 1 row in set (1.75 sec)
  

  


  • mysql> select count(id) from test;
  • +-----------+
  • | count(id) |
  • +-----------+
  • |   6003058 |
  • +-----------+
  • 1 row in set (1.87 sec)
  

  


  • mysql> select count(c1) from test;
  • +-----------+
  • | count(c1) |
  • +-----------+
  • |   6003058 |
  • +-----------+
  • 1 row in set (2.02 sec)
  

  从上面的执行时间看,前两条相差不多,第三条次之,最差的是第四条,看看explain的结果:
  


  • mysql> explain select count(1) from test;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • |  1 | SIMPLE      | test  | index | NULL          | PRIMARY | 4       | NULL | 6003369 | Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • 1 row in set (0.00 sec)
  

  


  • mysql> explain select count(*) from test;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • |  1 | SIMPLE      | test  | index | NULL          | PRIMARY | 4       | NULL | 6003369 | Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • 1 row in set (0.00 sec)
  

  


  • mysql> explain select count(id) from test;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • |  1 | SIMPLE      | test  | index | NULL          | PRIMARY | 4       | NULL | 6003369 | Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • 1 row in set (0.00 sec)
  


  • mysql> explain select count(c1) from test;
  • +----+-------------+-------+------+---------------+------+---------+------+---------+-------+
  • | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra |
  • +----+-------------+-------+------+---------------+------+---------+------+---------+-------+
  • |  1 | SIMPLE      | test  | ALL  | NULL          | NULL | NULL    | NULL | 6003369 |       |
  • +----+-------------+-------+------+---------------+------+---------+------+---------+-------+
  • 1 row in set (0.00 sec)
  

  由上可以看出,前三者的执行计划是一样的,第四条与前三者不同,没有使用覆盖索引,从执行时间上排序为:
  count(1)=count(*) < count(主键) < count(非主键字段)
  上面是未指定条件的情况,如果加上条件呢,看看下面三条语句:


  • 1.select count(1) from test where>
  • 2.select count(*) from test where>
  • 3.select count(id) from test where>4.select count(c1) from test where>
  下面是命令行下的执行情况:
  


  • mysql> select count(1) from test where id>0;
  • +----------+
  • | count(1) |
  • +----------+
  • |  6003058 |
  • +----------+
  • 1 row in set (2.07 sec)
  

  


  • mysql> select count(*) from test where id>0;
  • +----------+
  • | count(*) |
  • +----------+
  • |  6003058 |
  • +----------+
  • 1 row in set (2.07 sec)
  

  


  • mysql> select count(id) from test where id>0;
  • +-----------+
  • | count(id) |
  • +-----------+
  • |   6003058 |
  • +-----------+
  • 1 row in set (2.07 sec)
  

  


  • mysql> select count(c1) from test where id>0;
  • +-----------+
  • | count(c1) |
  • +-----------+
  • |   6003058 |
  • +-----------+
  • 1 row in set (2.28 sec)
  

  从上面的执行时间可以看到:


  • 1.count(1),count(*),count(主键)在执行时间上是差不多的,没有明显的差别
  • 2.count(非主键字段)的执行时间明显要比前三者长。
  再看一下explain的结果:
  


  • mysql> explain select count(1) from test where id>0;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra                    |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • |  1 | SIMPLE      | test  | range | PRIMARY       | PRIMARY | 4       | NULL | 3001684 | Using where; Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • 1 row in set (0.00 sec)
  

  


  • mysql> explain select count(*) from test where id>0;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra                    |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • |  1 | SIMPLE      | test  | range | PRIMARY       | PRIMARY | 4       | NULL | 3001684 | Using where; Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • 1 row in set (0.00 sec)
  

  


  • mysql> explain select count(id) from test where id>0;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra                    |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • |  1 | SIMPLE      | test  | range | PRIMARY       | PRIMARY | 4       | NULL | 3001684 | Using where; Using index |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
  • 1 row in set (0.00 sec)
  

  


  • mysql> explain select count(c1) from test where id>0;
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • |  1 | SIMPLE      | test  | range | PRIMARY       | PRIMARY | 4       | NULL | 3001684 | Using where |
  • +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
  • 1 row in set (0.00 sec)
  

  从上面的explain可以看到,前三种情况都会发生using index,即覆盖索引。


  • Using index:列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
  而最后的情况不会覆盖索引,会进行表读取,故速度会比前三者要慢,耗时更长就能理解了。
  结论:


  • 1.在mysql中,对于表类型innodb的情况,如果无条件,count(1),count(*)没有区别。
  • 2.如果有条件,则count(1),count(*),count(主键)没有区别
  • 3.对于count(非主键字段)的情况因为没有使用覆盖索引,耗时会比前三者更长,应避免这种写法。
  • 4.为了安全起见,建议只使用count(1)或count(*)进行统计,两者完全等价。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-611855-1-1.html 上篇帖子: mysql主从同步步骤 下篇帖子: MySQL查询的性能优化
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表