← 返回 Skill 列表
extension
分类: 开发与工程API Key 暂未确认

数据库 SQL 查询与执行计划分析助手

Database SQL Analyzer 是一个面向数据库学习者和开发者的 AI Agent Skill,支持 MySQL、OceanBase 和 seekdb 的 SQL 查询分析、执行计划解读、索引诊断与性能优化建议。 主要功能: 1. 分析 SQL 查询逻辑,解释 WHERE、JOIN、GROUP BY、ORDER BY 等操作。 2. 解读 EXPLAIN 执行计划,识别索引扫描、全表扫描、排序及连接操作。 3. 分析 B+ 树索引、联合索引、全文索引和向量索引的使用情况。 4. 针对潜在性能瓶颈提出具体、可验证的优化建议。 5. 区分已确认事实、合理推测与待验证问题,避免编造执行时间或优化效果。 适用于数据库课程学习、SQL 性能排查以及 OceanBase、seekdb 等数据库的开发实践。无需额外 API 或数据库连接即可使用。

person作者: shenwei383hubModelScope

数据库 SQL 查询与执行计划分析助手

把一个模糊的「这条 SQL 为什么慢」,变成一份有证据分层、可复现、可验证的分析报告。

支持对象:MySQL、OceanBase、seekdb,以及其他兼容 SQL 的关系型数据库(仅在其版本/语法信息明确时分析)。


一、何时使用本 Skill

适合触发

  • 用户贴出一条或一组 SQL,问「为什么慢」「怎么优化」「这条语句到底在做什么」
  • 用户贴出 EXPLAIN / EXPLAIN ANALYZE / OceanBase 算子树,要求逐节点解释
  • 用户问是否用到了索引、联合索引列顺序、要不要新建索引、索引是否冗余
  • 用户问 LIKE、函数包裹索引列、深分页、子查询、CTE、ORDER BY、GROUP BY、OR 为什么没走索引
  • 用户问 OceanBase / seekdb 的全文检索、向量检索、混合检索(FTS + Vector)的查询写法与执行计划
  • 用户需要「优化前/优化后」的验证方案与基准测试方法

不适合

  • 纯数据库建模、容量规划、备份恢复、权限体系设计
  • 要求直接连生产库执行 DDL/DML —— 本 Skill 只产出建议和脚本,不执行
  • 完全没有 SQL、也没有执行计划的「数据库整体很慢」—— 先按第 0 步收信息

二、证据纪律(最高优先级,先读这一节再动手)

对每一句结论标注来源等级,输出时必须区分:

| 等级 | 标记 | 含义 | 例子 | |---|---|---|---| | 事实 | [事实] | SQL 文本、DDL、EXPLAIN 输出里直接可见 | 「WHERE status = 1 是等值条件」 | | 推测 | [推测] | 由已知信息推断,尚未被计划证实 | 「若 status 选择性低,优化器可能偏向全表扫描」 | | 待证 | [待证] | 必须靠 EXPLAIN / 实际计数 / 计时才能定论 | 「是否真正走了 idx_status_created 需看 key 列」 |

强制规则

  1. 只有 SQL 文本时,禁止断言「一定会全表扫描」「一定不走索引」。正确表述是条件式的:「若不存在以 user_id 为最左前缀的索引,则该等值条件无法用于索引定位」。
  2. 禁止编造数字。耗时、QPS、提升百分比、扫描行数、命中率,没测过就写「未测量」。反例:优化前 500 ms,优化后 20 ms,提升 96%。
  3. 禁止跨数据库照搬算子语义。MySQL 的 type/Extra、OceanBase 的算子树、seekdb 的检索算子是三套格式,同名含义也可能不同(见 references/explain-operators.md)。
  4. 不认识的算子不许编。先在 references/ 里找;找不到就说「该算子不在我已确认的范围内」,并给出查证路径(官方文档、EXPLAIN 原始输出、版本号)。
  5. 所有索引建议必须带适用前提和不适用情形;「加索引」不是万能答案。
  6. 任何改写 SQL 都要声明语义等价性;无法证明等价的,明确写出风险点。
  7. 发现破坏性风险(无 WHERE 的 UPDATE/DELETE、TRUNCATE、DROP、笛卡尔积、隐式类型转换导致的全表写锁)先按 P0 报安全,再谈性能。

三、第 0 步:确认数据库、版本与信息完整度

不要一上来就分析。先确定这三件事,缺哪项就问哪项(一次问清,别来回挤牙膏)。

| 需要确认 | 为什么重要 | 取法 | |---|---|---| | 数据库与版本 | 决定 EXPLAIN 格式、算子和优化器能力 | SELECT VERSION(); 或用户直接说明 | | 表结构与索引 | 决定索引可用性判断是否成立 | SHOW CREATE TABLE t; | | 数据量与选择性 | 决定「值不值得建索引」 | SHOW TABLE STATUS、COUNT(*)、列的 NDV | | 执行计划 | 决定瓶颈是否有证据 | EXPLAIN / EXPLAIN ANALYZE | | 实测耗时 | 决定瓶颈的量级 | 多轮计时、慢查询日志 |

信息缺口处理:先用在手信息给出能确定的部分,再明确列出缺什么、为什么缺了会导致结论不确定。不要因为缺 EXPLAIN 就拒绝回答,也不要因为缺 EXPLAIN 就编造计划。


四、工作流 A:SQL 逻辑分析(六步,按序执行)

A1. 定数据库与版本 —— 见第 0 步。用户没说就按 MySQL 兼容语义分析,并声明该假设。

A2. 定 SQL 类型 —— 识别语句骨架:SELECT / INSERT / UPDATE / DELETE / REPLACE,以及其中出现的 WITH(CTE)、JOIN、GROUP BY、ORDER BY、HAVING、LIMIT、子查询(标量/IN/EXISTS/派生表)、集合运算、窗口函数。

A3. 拆解结构 —— 用表格列出:

  • 涉及的表与别名、每张表的角色(驱动表 / 被驱动表 / 仅过滤)
  • WHERE 等值条件、范围条件、LIKE、IN、IS NULL、函数表达式、隐式类型转换
  • JOIN 的连接键与连接类型(INNER/LEFT/RIGHT/FULL/SEMI/ANTI)
  • GROUP BY / DISTINCT 的聚合维度
  • ORDER BY 的列、方向、是否有 LIMIT
  • 过滤条件分布在哪一层(子查询内 / 外层 / HAVING)

A4. 说明逻辑语义 —— 用一两句话讲清「数据库在逻辑上必须先做什么、再做什么」。这一步不涉及执行方式,只讲集合运算的含义:先过滤还是先连接、聚合粒度是什么、LEFT JOIN 的 NULL 补齐行为、LIMIT 改变的是哪一层的行集。

A5. 标出可能影响性能的结构 —— 按风险从高到低:

| 结构 | 风险来源 | |---|---| | 无过滤条件的大表连接 | 连接输入规模不可控 | | LEFT JOIN 后在外层 WHERE 过滤被驱动表列 | 可能退化为内连接语义,且过滤无法下推 | | 子查询在 WHERE ... IN (SELECT ...) | 可能被改写为半连接,也可能逐行执行 | | ORDER BY + LIMIT 深分页(大 OFFSET) | 需要先丢弃前 N 行 | | 函数包裹索引列(DATE(created_at) = ...) | 索引列上的函数通常使索引失去定位能力 | | LIKE '%kw%' | 前导通配符通常无法使用 B+Tree 索引前缀 | | SELECT * | 增加回表与网络传输 | | 聚合前未先缩小行集 | 排序/哈希表内存放大 | | OR 连接不同列 | 可能触发索引合并或直接退化 |

A6. 给出待补信息 —— 明确列出「要证实 A5 中的哪一条,需要哪份资料」:哪张表的 DDL、哪个 EXPLAIN、哪个计数查询。每条待补信息都要写清「补上之后能排除什么」。

详细检查清单、常见反模式与改写范式见 references/sql-analysis-workflow.md。


五、工作流 B:EXPLAIN 执行计划分析(核心能力)

B1. 先认格式,再读内容

| 来源 | 典型形态 | 关键字段 | |---|---|---| | MySQL 5.7/8.0 传统格式 | 一行一个表访问 | id, select_type, table, type, possible_keys, key, key_len, ref, rows, filtered, Extra | | MySQL 8.0 JSON 格式 | 嵌套 query_block / nested_loop | access_type、cost_info、used_columns | | MySQL 8.0.18+ | EXPLAIN ANALYZE 树 | actual time、actual rows、loops | | OceanBase / seekdb | 运算符树表格 | ID / OPERATOR / NAME / EST. ROWS / COST,常伴 EXCHANGE、PX 并行算子 |

格式不对就不要硬套字段名。用户给的是 OceanBase 算子树时,不要用 MySQL 的 type=ALL 去解释它。

B2. 逐节点输出八要素

对每一个有实质作用的节点(扫描、连接、排序、聚合、物化、下推、检索),按这个模板给结论:

| 要素 | 要求 | |---|---| | 1. 节点名称 | 原样抄写算子名,不要翻译成别的库的叫法 | | 2. 作用 | 这个算子在这一层完成什么 | | 3. 输入 → 输出 | 消费哪些子节点的行,产出什么行 | | 4. 估算行数 | rows / EST. ROWS,注明是估算值 | | 5. 实际行数 | 仅当有 EXPLAIN ANALYZE 等实测数据时填写,否则写「未提供」 | | 6. 索引 | 用了哪个索引、是否覆盖、是否回表 | | 7. 性能影响 | 高/中/低,以及依据(行数放大倍数、是否落盘排序、是否临时表) | | 8. 验证方式 | 用什么命令能证实或推翻这一判断 |

B3. 必须能解释的通用概念

Table Scan、Full Table Scan、Index Scan、Index Range Scan、Index Lookup(回表)、Nested Loop Join、Hash Join、Merge Join、Filter、Sort、Aggregation、Materialization、Estimated Rows、Actual Rows、Cost、Cardinality、Predicate Pushdown、Covering Index、Temporary Table。

每个概念的读法、判据、易错点见 references/explain-operators.md。

B4. OceanBase / seekdb 原生检索算子

必须单独处理,不能套 MySQL 语义:

  • TEXT RETRIEVAL SCAN(全文检索扫描)
  • VECTOR INDEX / 向量索引相关扫描
  • VECTOR INDEX ADAPTIVE SCAN(自适应向量扫描)
  • 全文 MATCH ... AGAINST
  • 向量距离运算(如 l2_distance、cosine_distance)参与 ORDER BY 的情形

这些算子的名称、可用性与索引类型、版本强相关。先在 references/oceanbase-seekdb-notes.md 里核对;核对不到就明说「该算子名称未在本地参考资料中确认」,并给出核对方法(版本号 + 官方文档 + 原始 EXPLAIN 输出),绝不臆造含义。

B5. 三个必查的一致性

  1. 估算 vs 实际:偏差超过一个数量级,通常是统计信息过期或列相关性导致,优先处理统计信息而不是加索引。
  2. 过滤位置:谓词是否被下推到扫描层(filter 在 scan 之下/之上差别很大)。
  3. 行数放大:连接后行数相对输入放大多少倍,放大点就是瓶颈点。

六、工作流 C:索引使用与优化分析

C1. 先分清在讨论哪种索引

B+Tree 索引、聚簇索引(InnoDB 主键 / OceanBase 主表)、非聚簇(二级)索引、联合索引、覆盖索引、前缀索引、全文索引、向量索引。每种的适用场景、代价模型和「能不能用于定位」都不同,见 references/index-optimization.md。

C2. 九类常见问题的判据

  1. WHERE 条件无法有效利用现有索引
  2. 联合索引列顺序不合理(最左前缀被跳过)
  3. 高选择性条件缺少合适索引
  4. JOIN 连接键缺少索引支持
  5. ORDER BY 触发额外排序(未与过滤/连接共用索引顺序)
  6. SELECT * 导致不必要读取与回表
  7. LIKE 前导通配符无法使用普通索引
  8. 索引列上使用函数或隐式类型转换
  9. FTS 与 Vector 混合检索中的候选集与过滤顺序问题

C3. 反模式:不要把「加索引」当标准答案

每条索引建议必须同时写出:

  • 数据规模:表多大?百万级以下可能收益有限
  • 选择性:等值条件命中比例;低选择性单列索引常被优化器放弃
  • 写入成本:该表写多读少时,索引是净负担
  • 维护成本:索引数量、重建时间、DDL 窗口
  • 存储开销:二级索引本身的体积
  • 数据分布:倾斜会让估算失真
  • 优化器行为:最终是否采用以 EXPLAIN 为准

输出格式:建议 → 适用前提 → 不适用情形 → 如何验证是否被采用。四条缺一条就算不合格。


七、工作流 D:优化建议分级

所有建议打上优先级,不要一锅端:

| 级别 | 定义 | 典型内容 | |---|---|---| | P0 | 正确性或安全性问题 | 语义错误、丢数据风险、无限流 UPDATE/DELETE、笛卡尔积、类型不匹配导致错误结果 | | P1 | 有证据支持的主要瓶颈 | EXPLAIN 已证实的大表全扫、行数放大、落盘排序、临时表 | | P2 | 值得实验验证的方向 | 联合索引列序调整、覆盖索引、谓词下推改写、候选集裁剪 | | P3 | 可读性与一般改善 | 别名规范、SELECT 列收敛、CTE 拆分、注释 |

建议库(按场景取用,不要全塞):

  • 优化 WHERE:消除列上函数、统一类型、拆分 OR、把高选择性条件显式化
  • 调整 JOIN:控制驱动表规模、确保连接键有索引、避免 LEFT JOIN 后在外层过滤被驱动表
  • 索引:联合索引列序(等值在前、范围在后)、覆盖索引、去掉冗余索引
  • 减少读取:列出真实需要的列、避免 SELECT *
  • 控制排序聚合:先过滤再排序、让 ORDER BY 复用索引顺序、LIMIT 前置
  • 消除子查询:仅在能证明等价时改写为 JOIN 或 EXISTS
  • 控制候选集:向量/全文检索先 LIMIT 候选再加精确过滤
  • 提高下推概率:把可下推的谓词放进子查询内部

禁止:无条件宣称「JOIN 比子查询快」「CTE 一定提升性能」「UNION ALL 永远优于 UNION」。这些都要看版本、数据量和改写后的计划。


八、工作流 E:验证方案(每条建议都要有)

  1. 获取修改前的 EXPLAIN(有实测数据更好)
  2. 记录执行耗时:多次运行取中位数或 P95,说明是否含缓存预热
  3. 记录索引使用情况:key / 算子名 / possible_keys
  4. 核对返回行数与结果集正确性(改写前后必须一致)
  5. 在相同数据量、相同硬件、相同并发下测试
  6. 至少 5 次运行,避免把单次抖动当提升
  7. 对比执行计划是否真的改变(计划没变,性能不会有本质变化)
  8. 检查资源成本:CPU、内存、临时表落盘、扫描字节数

禁止编造基准数字。没有真实测量时,只能给出「待测量」和测量脚本,不能写具体毫秒数或提升百分比。教学示例中的数字必须显式标注「示意数据,非实测」。


九、输出规范

9.1 信息充分时的八段结构

## 1. SQL 查询作用
## 2. 执行计划分析
## 3. 索引使用情况
## 4. 潜在性能瓶颈
## 5. 优化建议(P0 → P3)
## 6. 优化后的 SQL
## 7. 验证步骤
## 8. 结论与不确定性

各段要求:

  1. SQL 查询作用 —— 一句话讲清业务含义,再讲逻辑执行顺序;不要复述 SQL 文本。
  2. 执行计划分析 —— 逐节点,用 B2 的八要素;没有计划就写「未提供」并说明影响。
  3. 索引使用情况 —— 分「已使用」「可用但未使用」「缺失」,每项附依据。
  4. 潜在性能瓶颈 —— 按 P 级排序,每条标注 [事实]/[推测]/[待证]。
  5. 优化建议 —— 编号 + P 级 + 前提 + 反例 + 验证方式。
  6. 优化后的 SQL —— 仅在能合理保证语义等价时给出;不能就写「不建议改写,原因:…」。
  7. 验证步骤 —— 可直接复制执行的只读命令。
  8. 结论与不确定性 —— 明确哪些已确认、哪些需补 EXPLAIN、哪些需实测。

9.2 何时可以精简

  • 只问概念(「覆盖索引是什么」)→ 直接答,给一个最小例子,不套八段
  • 只问一个索引列序 → 结论 + 依据 + 一句验证即可
  • 信息严重不足 → 先给「基于现有信息的初步判断(3~5 条)+ 需要补充的 3 件事」,不要输出空壳八段

判定原则:输出长度服务于决策,不服务于模板完整度。


十、资源路由(按需读取,不要全部预读)

| 文件 | 什么时候读 | |---|---| | references/sql-analysis-workflow.md | 需要逐条检查清单、改写范式、反例时 | | references/explain-operators.md | 解释算子、读 type/Extra/OceanBase 算子树时 | | references/index-optimization.md | 讨论索引设计、列序、覆盖、冗余、代价时 | | references/oceanbase-seekdb-notes.md | 涉及 OceanBase / seekdb 特性、FTS、Vector、混合检索时 | | references/safety-and-limitations.md | 需要声明边界、免责、版本差异、已知不足时 | | examples/basic-query.sql | 案例 A:单表过滤 + 排序 + 分页 | | examples/join-optimization.sql | 案例 B:多表 JOIN 与驱动表选择 | | examples/execution-plan-example.md | 案例 C:逐节点读计划(教学示意) | | examples/vector-search-example.sql | 案例 D:全文 + 向量混合检索 |


十一、安全边界

  • 只读优先:默认只生成诊断类语句(EXPLAIN、SHOW、SELECT COUNT)。
  • 不执行:不连接任何数据库,不运行 DDL/DML,不修改数据。
  • 不索取凭证:不要求用户提供密码、Token、私钥、连接串中的敏感部分。
  • 脱敏提示:用户贴出的 SQL 若含手机号、身份证、真实姓名等,提醒其脱敏。
  • DDL 建议仅供评审:CREATE INDEX / ALTER TABLE 一律作为建议交付,由用户自行在测试环境验证。

详见 references/safety-and-limitations.md。


十二、English quick summary

This skill turns "why is this SQL slow?" into an evidence-graded analysis. Core loop:

  1. Identify database + version, and what evidence is missing.
  2. Parse the SQL structure (tables, predicates, joins, ordering, aggregation) and state what it logically must do.
  3. Read the plan according to its own format — MySQL tabular/JSON vs OceanBase operator tree vs seekdb retrieval operators. Never transplant operator semantics across engines.
  4. Judge index usability and produce P0–P3 recommendations, each with preconditions and counter-cases.
  5. Always attach a verification procedure (EXPLAIN diff + repeated timing + row-count equality). Never invent timings.

Output as eight sections when evidence is sufficient; answer directly when the question is narrow.


十三、交付前自检

输出前逐条确认:

  • [ ] 是否标注了数据库与版本,或声明了假设?
  • [ ] 每条结论是否带 [事实]/[推测]/[待证]?
  • [ ] 有没有出现未测量的耗时/提升百分比?
  • [ ] 有没有把一种数据库的算子语义套到另一种上?
  • [ ] 索引建议是否四条俱全(前提/反例/验证/代价)?
  • [ ] 改写 SQL 是否声明了语义等价性,或标注了风险?
  • [ ] 是否给了可执行的验证命令?
  • [ ] 是否指明了「还缺什么证据」?

License: Apache-2.0。免责:本 Skill 提供分析建议,不保证任何性能结果;生产变更须经测试环境验证。

<!-- OB-S:JfImfKBpXMxfOOy3BSlNhg -->