SELECT COUNT(*)会不会造成全表扫描?

简介:SELECT COUNT(*)会不会造成全表扫描?

最近在网上冲浪时看到有人说COUNT(*)会造成全表扫描,自己平时开发时还真没有注意到这个细节,干脆我就自己实验一下真伪。

实验准备

准备一张表并添加测试数据。我担心少量的数据测试不错效果,我使用了我自己项目的访问记录表来演示

CREATE TABLE `visit_log` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `uid` int unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
  `app_type` varchar(50) NOT NULL DEFAULT '' COMMENT 'app唯一标识,区分小程序,公众号,app等',
  `add_time` int unsigned NOT NULL DEFAULT '0' COMMENT '访问时间',
  `client_ip` varchar(20) NOT NULL DEFAULT '' COMMENT '客户端ip',
  `unit_type` varchar(20) NOT NULL DEFAULT '' COMMENT '设备型号',
  `user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT '请求头信息',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='访问日志表'

上述测试表中只有一个主键,没有其他索引。

下面我们使用expalin分析 select count(*) 统计总记录数的SQL:

使用explain分析SQL(不了解MySQL中的explain的可以查看我的另一篇文章【MySQL explain详解】):

  • type=index:说明使用了索引
  • key=primary:最总使用了主键索引
  • key_len:索引长度4字节(我的主键id用的是int,正好占4字节)

注意:此时表只有一个主键,使用count(*)在没有其他where条件的前提下会走主键索引。

现在我们给表添加一个普通索引:

alter table visit_log add index appTypeIndex(app_type);

此时我们的表中有一个主键(id)和一个普通索引(app_type),接下来我们再使用count(*)查询看看其结果:

观察发现type=index说明使用了索引,但是key=appTypeIndex。这是为什么呢?

此时有点懵逼,于是再给表添加了一个索引:

alter table visit_log add index addTimeIndex(add_time);

再使用explain分析select count(*) from visit_log:

不难发现,此时count(*)依然使用了索引,只是使用的索引是我们新添加的索引。好吧,我们先不总结,再来看看count(1),count(主键字段),count(index),count(无索引字段)分别会有什么效果吧

  • count(1)

  • count(主键字段)

  • count(index)

  • count(无索引字段)

实验结束,我们来总结一下吧!在没有使用where前提下:

  1. count(index):会使用当前index字段指定的索引
  2. count(无索引):不会使用任何索引
  3. count(1)、count(*)、count(id)这三类都是一样的,都会使用表中索引长度最小的那个

下面我们再来看看有where条件会是什么情况。

  • 首先我们看看where使用了索引字段,count(无索引)

  • where使用了索引,count(id)

  • where使用了索引,count(index)并且where索引字段与count的索引字段相同

  • where使用了索引,count(index)并且where索引字段与count的索引字段不同

  • where不使用索引,count(index)

观察上述SQL及分析结果,在使用where条件时count即使使用了索引字段,也不一定使用索引,是否使用索引由where条件决定。原因其实也很简单,毕竟where条件需要根据表中的数据进行分析查找,关于where优化还有一个最左前缀优化原则问题,有兴趣的朋友可以看看我的另一篇文章【MySQL优化-索引优化

有遗漏或者不对的可以在我的公众号留言哦

编程经验共享公众号二维码

编程经验共享公众号二维码
更多内容关注公众号
Copyright © 2021 编程经验共享 赣ICP备2021010401号-1