SQL 执行计划诊断(sql-explain-doctor)
把执行计划变成“先修什么、为什么、怎么验证”的三段式结论,避免只丢一句“加索引”。
何时使用
- 用户提供了
EXPLAIN、EXPLAIN FORMAT=TREE、EXPLAIN ANALYZE的输出(MySQL 8.x、OceanBase、seekdb)。 - 用户问:“这条 SQL 为什么慢”“要不要加索引”“为什么没走索引”“这个计划合理吗”。
不适用
- 只有 SQL 文本、没有执行计划:先请用户执行
EXPLAIN <SQL>并贴回结果。 - 需要压测、参数调优、锁等待或资源瓶颈分析:超出本技能范围,说明原因并建议补充的信息。
- 没有表结构(
SHOW CREATE TABLE)与数据量时,不下“必须加索引”的定论,只给候选建议。
工作流程
-
判断格式:计划是表格型(含
type/key/rows列)还是树型(含OPERATOR/EST.ROWS)。 -
跑脚本:把计划原文存成文本文件,执行
python scripts/explain_report.py --input plan.txt也可
--input -从标准输入读,--format json输出结构化结果。脚本只读、离线、无第三方依赖。 -
人工复核:脚本是启发式规则,必须结合 SQL、表数据量、现有索引确认;拿不准的结论标“待确认”,不要直接断言。
-
输出报告:结论速览表 + 逐条建议(证据 → 动作 → 验证方式)+ 需要用户补充的信息。
-
给出验证路径:
EXPLAIN ANALYZE看真实耗时、SHOW INDEX FROM t看现有索引、ANALYZE TABLE更新统计信息。
规则表(脚本内置)
| 规则 | 触发条件 | 优先级 | 建议方向 |
| --- | --- | --- | --- |
| R01 | type=ALL 且 rows ≥ 1000 | P0 | 全表扫描:为过滤/连接列建索引,或收窄条件 |
| R02 | key 为空且 rows ≥ 10000 | P1 | 未命中任何索引:检查条件是否可索引、是否发生隐式转换 |
| R03 | possible_keys 非空但 key 为空 | P1 | 有候选索引没用上:看选择性、函数包裹、最左前缀 |
| R04 | 多表连接中 ≥ 2 个表 type=ALL | P1 | 被驱动表缺索引,或连接顺序需要调整 |
| R05 | rows ≥ 100000 | P1 | 扫描行数过大:先过滤再连接,避免全量聚合 |
| R06 | Extra 含 Using filesort | P2 | 排序无法用索引:考虑 (过滤列, 排序列) 联合索引 |
| R07 | Extra 含 Using temporary | P2 | 临时表:常见于 GROUP BY / DISTINCT / UNION,考虑覆盖索引 |
| R08 | type=index | P2 | 全索引扫描:确认是否真的需要遍历整棵索引 |
| R09 | filtered < 10 且 rows ≥ 10000 | P2 | 过滤性差:索引选择性不足,考虑联合索引或改写 |
| T01 | 树型计划中 TABLE SCAN 且估算行数 ≥ 10000 | P1 | 大表全扫描:同 R01 |
| T02 | 树型计划中出现 TEMP TABLE / SORT | P2 | 排序或临时表算子:同 R06 / R07 |
| T03 | 树型计划中 NESTED LOOP 与 TABLE SCAN 同时出现 | P1 | 嵌套循环内层全扫描:内层连接列建索引 |
输出格式
# EXPLAIN 诊断报告
- 输入格式:表格型 / 树型
- 计划条目:N 条
- 命中规则:R01、R05 ...
## 结论速览
| 优先级 | 规则 | 问题 | 位置 | 依据 |
## 逐条建议
### P0 · R01 全表扫描(表 o)
- 证据:type=ALL,rows=980000
- 动作:为 o.user_id 建索引 / 改写为按时间范围过滤
- 验证:再次 EXPLAIN,确认 type 变为 range 或 ref
## 需要补充的信息
- 表结构与现有索引(SHOW CREATE TABLE)
- 真实耗时(EXPLAIN ANALYZE)
示例
python scripts/explain_report.py --input examples/sample_explain.txt
样例计划与期望报告见 examples/。
质量检查
- [ ] 每条结论都能指回计划里的某一行、某一列
- [ ] 区分“计划显示的事实”与“我的推测”,推测标注待确认
- [ ] 索引建议写明列顺序与理由,并提示评估写入放大
- [ ] 不承诺具体提速倍数,改用“预期减少扫描行数”这类可验证表述
微信扫一扫