慢查询拆解:从执行计划到索引,一步步收敛
给出一条慢 SQL 和表结构,产出可验证的优化路径,而不是「加个索引试试」。
提示词(整段复制)
你是数据库优化工程师。请分析下面这条慢查询。
SQL:
```sql
{{SQL}}
```
涉及表结构与索引:{{表结构}}
数据量与分布:{{数据量}}
执行计划关键行:{{执行计划}}
数据库类型与版本:{{数据库}}
输出要求:
1. **读计划**:逐行说明 MySQL/PG 这一步在做什么,重点指出 type/key/rows/filtered 或对应的 PG 字段含义。
2. **定位瓶颈**:明确是「扫了太多行」「回表太多」「排序/临时表」「锁等待」中的哪一种,给出判断依据。
3. **索引方案**:给出具体的联合索引定义(字段顺序要解释),并说明它为什么能命中、是否覆盖。
4. **反例**:说明「加一个单列索引」为什么不够(或够)。
5. **不改索引的替代方案**:如改写法(子查询转 join、去掉函数包裹、分页改写)。
6. **验证方法**:改完用什么命令、看哪个指标确认生效。
约束:
- 不写「建议优化 SQL 语句」这类空话,每条建议都要能直接执行。
- 如果信息不足以判断,明确说缺哪一项,不要编造执行计划。复制时把 {{变量}} 换成你自己的内容;变量名不要改,改了模型容易把它当普通文字。
要替换的变量
实操建议
- `DATE(created_at)` 这种函数包裹会让索引失效,是最常见的隐形全表扫
- status 区分度只有 15%,单列索引几乎没用——这一点要模型明确指出来
常见问题
为什么加了索引还是不生效?
常见三种:字段被函数包裹、隐式类型转换(字符串查数字列)、联合索引字段顺序与该查询的最左前缀不匹配。
联合索引字段顺序怎么定?
等值条件在前、范围条件在后,区分度高的等值条件更靠前。本例应是 (status, created_at)。
