
一次看似简单的 SQL 查询,如何将扫描 2279 万行优化到精准定位,实现 100 倍性能提升?
某天收到数据库告警,提示 CPU 使用率过高。明明前段时间才扩容过,按理说不至于又撑不住。上云平台一查,发现嫌疑 SQL 居然扫描了 2000 万行,而这个表总共才 3000 万行。

嫌疑 SQL 如下:
SELECT a.amount, a.record_time FROM coin AS a WHERE a.uid=? AND a.record_time>=? AND a.record_time<? AND a.flow_id<? ORDER BY a.flow_id DESC LIMIT ?我记得这个表同事加过索引,索引如下:
KEY `idxxxx` (`uid`, `record_time`, `flow_id`)相信细心的同学已经一眼看出问题了。
有些人可能会疑惑,为什么索引顺序没问题,扫描的行数却这么多,感觉索引根本没用上。
我们先用 explain 看一下。

关键问题出现在 Using filesort ——这个信号说明 MySQL 正在执行昂贵的排序操作。
为什么原有索引效率低下?
那应该怎么建立索引才合理呢?
答案如下:
KEY idx_uid_flowid_recordtime (uid, flow_id, record_time)为什么换个顺序就有效了?
flow_id 排序,天然支持 ORDER BY flow_id DESCuid= 快速定位用户数据flow_id 倒序扫描,遇到不满足条件的立即停止record_time 进行过滤来看下优化后的 explain。

可以看到,Extra 已经是 Using Where,没有了之前的排序操作,效率大大提升。
Extra 的各个阶段:
Using filesort:需要额外排序 → 性能较差Using where:在存储引擎层过滤 → 良好状态Using index:覆盖索引,最优状态 → 下一步优化目标PS:我这边需要查询大量数据,必须回表,所以最多只能优化到 Using Where。把所有字段都放到索引里的成本太高了。
优化后执行时间大约是 14ms,之前监控显示为 1.13s,提升了 80 倍,差不多可以说是提升了 100 倍。

这次优化经历再次证明:合理的索引设计是数据库性能的基础。深入理解查询特性和索引原理,才能将性能优化做到极致。
优化没有终点,每一次性能提升都是对技术理解的进一步加深。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。