EXPLAIN 里 type=ALL 出现三次,慢查询就有了答案
【摘要】 现象订单列表接口 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)