原文:mysql 5.7 innodb count count(*) count(1) 大数据 查询慢 耗时多 优化
问题描述
mysql 5.7 innodb 引擎 使用以下几种方法进行统计效率差不多,都不是很高,实际使用中,博客表2万条数据就耗时1秒多,效果不堪。在可以为 null 的字段上统计,效率更低。数据如下:
select count(*) from blog;
select count(1) from blog;
select count(id) from blog;
(三个差不多,统计25826行,耗时:1.14 sec)
select count(modtime) from blog;
(modtime可以为null,统计25826行,耗时:1.63 sec)
解决方案:对 id 建立 unique 索引
ALTER TABLE `blog`
ADD UNIQUE INDEX `blog_id`(`id`) USING BTREE;
建立 unique 索引后,再进行统计:
select count(*) from blog;
select count(1) from blog;
select count(id) from blog;
(三个相同,统计25826行,耗时:0.03 sec)
select count(modtime) from blog;
(modtime可以为null,统计25826行,耗时:1.51 sec)
原因分析
- 为什么可以为 null 的字段效率最低:因为每次都要进行判空操作。
- count(1) count(* ) count(主键)哪个快:实际使用中差不多,本质都是互相调用
- 为什么主键加 unique 后统计效率会提高几十倍:innodb 引擎统计时大部分情况下统计的是主键,由于主键索引与数据文件存放在一起,所以每次都会扫描数据文件(大量随机io)。加 unique 后,会将主键按规则缓存在内存中,统计时直接统计内存中数据,效率提升几十倍。