慢查询拆解:从执行计划到索引,一步步收敛

给出一条慢 SQL 和表结构,产出可验证的优化路径,而不是「加个索引试试」。

什么时候用:一条 SQL 从 200ms 变成 8 秒,看执行计划看不懂,加索引有的生效有的不生效。

提示词(整段复制)

你是数据库优化工程师。请分析下面这条慢查询。

SQL:
```sql
{{SQL}}
```
涉及表结构与索引:{{表结构}}
数据量与分布:{{数据量}}
执行计划关键行:{{执行计划}}
数据库类型与版本:{{数据库}}

输出要求:
1. **读计划**:逐行说明 MySQL/PG 这一步在做什么,重点指出 type/key/rows/filtered 或对应的 PG 字段含义。
2. **定位瓶颈**:明确是「扫了太多行」「回表太多」「排序/临时表」「锁等待」中的哪一种,给出判断依据。
3. **索引方案**:给出具体的联合索引定义(字段顺序要解释),并说明它为什么能命中、是否覆盖。
4. **反例**:说明「加一个单列索引」为什么不够(或够)。
5. **不改索引的替代方案**:如改写法(子查询转 join、去掉函数包裹、分页改写)。
6. **验证方法**:改完用什么命令、看哪个指标确认生效。

约束:
- 不写「建议优化 SQL 语句」这类空话,每条建议都要能直接执行。
- 如果信息不足以判断,明确说缺哪一项,不要编造执行计划。

复制时把 {{变量}} 换成你自己的内容;变量名不要改,改了模型容易把它当普通文字。

要替换的变量

变量示例值
{{SQL}}SELECT * FROM orders WHERE DATE(created_at) = '2026-10-01' AND status = 1 ORDER BY id DESC LIMIT 20
{{表结构}}orders(id PK, created_at datetime, status tinyint, user_id, amount),已有索引 (status)
{{数据量}}1,200 万行,每天新增约 3 万行,status=1 占 85%
{{执行计划}}type=ALL, rows=12000000, Extra=Using where; Using filesort
{{数据库}}MySQL 8.0

实操建议

常见问题

为什么加了索引还是不生效?

常见三种:字段被函数包裹、隐式类型转换(字符串查数字列)、联合索引字段顺序与该查询的最左前缀不匹配。

联合索引字段顺序怎么定?

等值条件在前、范围条件在后,区分度高的等值条件更靠前。本例应是 (status, created_at)。

配套工具