EXPLAIN 里 type=ALL 出现三次,慢查询就有了答案

举报
ouyang_123 发表于 2026/11/11 08:14:40 2026/11/11
【摘要】 现象订单列表接口 P99 到了 4.2 秒,慢查询日志里同一条 SQL 一天出现 8000 次。按直觉给 user_id 加了索引,耗时只从 4.2 秒降到 3.9 秒。 判据先看执行计划,不要先加索引:EXPLAIN SELECT id, order_no, amountFROM ordersWHERE shop_id = 12 AND status = 1 AND created_at...

现象

订单列表接口 P99 到了 4.2 秒,慢查询日志里同一条 SQL 一天出现 8000 次。按直觉给 user_id 加了索引,耗时只从 4.2 秒降到 3.9 秒。

判据

先看执行计划,不要先加索引:

EXPLAIN SELECT id, order_no, amount
FROM orders
WHERE shop_id = 12 AND status = 1 AND created_at > '2026-10-01'
ORDER BY created_at DESC
LIMIT 20;

三个字段是判据:

  • type:出现 ALL 是全表扫,出现 index 是全索引扫,都不是好事;目标是 ref 或 range。
  • rows:估算扫描行数,跟返回行数差几个数量级就有问题。
  • Extra:出现 Using filesort 或 Using temporary,说明排序或分组没走索引。

我这条 type=ALL、rows=180万、Extra=Using where; Using filesort。

根因

索引建在 user_id 上,但这条查询的过滤条件是 shop_id + status + created_at,user_id 一次都没用到。优化器看不到能用的索引,只能全表扫再排序。

真正该建的是覆盖这三个字段的联合索引,而且顺序要对:等值条件在前,范围条件在后。

修法

ALTER TABLE orders
  ADD INDEX idx_shop_status_time (shop_id, status, created_at);

顺序的理由:shop_id 和 status 是等值过滤,放前面能先把范围缩小;created_at 是范围条件,放最后才能被索引用于排序,消掉 filesort。

再看一次执行计划确认:

EXPLAIN SELECT ... ;
-- type=range, rows=2400, Extra=Using index condition

验证

  • 扫描行数从 180 万降到 2400,下降 750 倍。
  • 查询耗时从 4.2 秒降到 0.031 秒,P99 从 4.2 秒降到 0.09 秒。
  • Using filesort 消失,排序直接在索引上完成。
  • 索引新增占用磁盘 96MB,写入耗时增加 3%(每次插入多维护一棵 B+ 树),可以接受。
  • 慢查询日志里这条 SQL 从每天 8000 次降到 0 次。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。