一次线上慢查询的完整排查记录

林 林亦然 2026年09月27日 · 2 分钟阅读 · 44 次浏览

一次线上接口超时,排查了六个小时,最后发现是一个很小的问题。记录下来,希望别人不要再踩。

现象

每天上午 10 点左右,某个查询接口 P99 从 80ms 涨到 3s 以上,持续约 10 分钟后自行恢复。

排查过程

1. 先看监控

CPU、内存、连接数都没明显变化,只有慢查询数量飙升。

2. 抓慢查询

sql
SELECT * FROM orders
WHERE created_at > $1
ORDER BY created_at DESC
LIMIT 20;

执行计划显示走了全表扫描。created_at 上明明有索引。

3. 真相

传入的参数是字符串,而字段是 timestamptz,类型不匹配导致索引失效。上午 10 点恰好有一个定时任务用字符串传参。

修复

  • 参数改成强类型绑定
  • 增加了一条索引
  • 补充了一个回归用例
php
$stmt = $pdo->prepare('SELECT * FROM orders WHERE created_at > ? ORDER BY created_at DESC LIMIT 20');
$stmt->execute([new DateTimeImmutable($input)]);

复盘

  • ✓参数类型必须在入口处校验
  • ✓慢查询告警阈值从 1s 调到 500ms
  • 给所有时间字段查询补一遍索引检查

教训:索引存在不等于索引生效,类型隐式转换是最容易被忽略的杀手。

♡ 0 人觉得有帮助 最后更新 25 天前
林
林亦然
资深后端工程师

评论 · 1

登录 后可以参与评论。
系
系统管理员 25 天前
补充一点:上线前用 EXPLAIN 过一遍关键查询,成本很低收益很高。