1. 引言

适合订单列表、用户记录、日志表这类按条件筛选并排序的查询优化。

接口偶尔变慢时,很多人会先怀疑服务器配置。实际项目里,更常见的原因是 SQL 没走索引,或者走了一个不合适的索引。尤其是"按用户筛选,再按时间倒序取最新记录"的接口,数据量一上来就容易拖慢。

这篇用一条订单查询做例子,从记录 SQL、查看执行计划、补组合索引到复测耗时,走一遍完整流程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 先拿到真实 SQL

优化前要拿到接口实际执行的 SQL,而不是凭印象改。ORM 生成的语句可能带额外字段、默认排序或软删除条件,这些都会影响索引选择。

-- 示例慢查询
SELECT *
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;

这类 SQL 的目标很明确:先筛出某个用户的订单,再按创建时间倒序拿最近 20 条。索引也应该围绕这个访问路径设计。

3. 用 EXPLAIN 看扫描方式

执行 EXPLAIN 后,重点看 typerowskey。如果 typeALL,说明可能在全表扫描;如果 rows 很大,说明数据库需要检查大量记录才能返回结果。

-- 查看执行计划
EXPLAIN
SELECT *
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;

在订单表有百万级数据时,全表扫描会非常明显。即使最终只返回 20 行,数据库也可能先扫很多行,再排序,再截取结果。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fmedia-internal-file.obs.cn-north-4.myhuaweicloud.com%3A443%2Fblog%2Fmp%2F6a66a90a0b55457f932d4cd71f21af87.docx%3FAccessKeyId%3DP2MIYLSC61SDC5UX2NCL%26Expires%3D1787654385%26Signature%3DheTNT4YZbLZ8RqYiCSoQmkSxSYg%253D&pos_id=img-NCJxMDHr-1787653179377

4. 补一个符合查询顺序的索引

这条查询既有等值条件,又有排序条件。单独给 user_id 建索引可以减少筛选范围,但排序仍可能额外发生。更合适的是组合索引:把 user_id 放前面,把 created_at 放后面。

-- 添加组合索引
CREATE INDEX idx_orders_user_created
ON orders(user_id, created_at DESC);

索引顺序要贴合查询条件。user_id 是等值筛选,放在前面;created_at 是排序字段,接在后面。这样数据库可以沿着索引直接拿到目标用户的最新订单。

在这里插入图片描述

不要看到慢查询就无脑加索引。每个索引都会增加写入成本和存储占用,线上表加索引前要评估数据量、锁表风险和业务低峰窗口。

5. 复测执行计划和接口耗时

索引加完后,再跑一次 EXPLAIN。理想情况下,key 会命中新建的组合索引,type 不再是 ALLrows 也会明显下降。

-- 复测查询
EXPLAIN
SELECT *
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;

执行计划只是第一步,还要看接口真实耗时。建议在测试环境用相近数据量复现,再观察线上慢查询日志。只要查询条件稳定,组合索引通常能把这类列表接口从秒级压到毫秒级。

6. 顺手检查 SELECT 字段

SELECT * 在教程里写起来方便,但生产代码里建议只取页面需要的字段。字段越多,回表和网络传输的成本越高。列表页通常只需要订单号、金额、状态、创建时间,不一定要把备注、地址、扩展 JSON 一起查出来。

7. 总结

慢查询优化不是只会加索引。拿到真实 SQL、看执行计划、设计索引、复测耗时,这四步走完整,才算把问题闭环。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐