前言

前几天,我优化过不少慢查询SQL语句。

count(*)这个慢查询的问题,比较特殊,让我影响很深刻,今天跟大家分享一下。

案发现场

我从archery上的慢查询记录中,看到了一条count(*)的慢查询SQL。

该SQL语句大概是这样的:

select count(*) from sku
inner join spu on spu.id=sku.spu_id
where sku.status=1 and spu.status=1

统计商品和商品组表中,状态同时为有效的商品数量有多少。

这条SQL在生产环境执行,耗时竟然达到了1.7s。

查询条件只有status,重复率很高。

这条SQL性能要如何优化呢?

分析问题

虽然上面的SQL查询条件只有status,但还是可以增加索引,提升一下性能。

我使用explain关键字,查了执行计划,发现该SQL语句已经走了两个索引。

一个索引是给sku表的status字段增加的普通索引,另一个索引是给spu表的status字段增加的普通索引。

我去,两个索引都走了。

但性能还是这么差,该怎么优化呢?

正常情况下,表的count(*)是没这么慢的。

表有很多垃圾数据,影响了性能?

解决问题

为了验证我的猜想,使用了optimize关键字,重新组织了一下表和索引。

对于一些经常做删除的表,很容易产生很多磁盘碎片。

而使用optimize关键字重新组织表和索引之后,可以减少存储空间,提升访问的I/O效率。

optimize table material_spu;
optimize table material_sku;

商品组和商品表,确认存在经常删除和修改的情况,可能会存储很多磁盘碎片。

优化之后,减少了约40%的存储空间。

重新执行那条count(*)的查询语句,发现执行效率提升了1s,目前只需0.7s。

优化之后,那条SQL的性能基本上能够满足要求了。

其实,optimize关键字 ,除了重新组织表和索引之外,还能重新收集统计信息。

最后修改:2026 年 06 月 06 日
如果觉得我的文章对你有用,请随意赞赏