简介: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详解】):
注意:此时表只有一个主键,使用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(无索引字段)分别会有什么效果吧
实验结束,我们来总结一下吧!在没有使用where前提下:
下面我们再来看看有where条件会是什么情况。
观察上述SQL及分析结果,在使用where条件时count即使使用了索引字段,也不一定使用索引,是否使用索引由where条件决定。原因其实也很简单,毕竟where条件需要根据表中的数据进行分析查找,关于where优化还有一个最左前缀优化原则问题,有兴趣的朋友可以看看我的另一篇文章【MySQL优化-索引优化】
有遗漏或者不对的可以在我的公众号留言哦