<!-- title: SQL优化Skill开发实战 -->

# Claude Code Skill开发实战：构建一个可运行的SQL优化助手

## 概述

本教程以"SQL查询优化助手"为载体，完整演示从需求拆解到评测上线的 Claude Code 自定义 Skill 开发全流程。你将掌握 SKILL.md 的 frontmatter 工程化、渐进披露（Progressive Disclosure）的分层落地、可执行脚本的封装与权限收敛、以及用 eval 量化触发精度。适合已跑通过 Claude Code 基础用法、希望把团队经验沉淀为可复用能力的开发者和 Tech Lead。

## 前置条件

- Claude Code 已安装并完成认证（CLI 或 IDE 任一入口）
- 基本熟悉在交互模式下发起对话、运行 `/` 命令
- 一台装有 Python 3.8+ 与 `git` 的开发机（示例脚本用 Python）
- 任意一个 git 仓库目录作为练习沙箱

---

## 第一步：先想清楚——什么样的能力才值得做成 Skill

很多人上手就建 `SKILL.md`，这是最常见的浪费。Skill 不是"把提示词存起来"，而是**一段可被模型在恰当场景自动调用的、带资源约束的能力封装**。在动手前，用三个问题自检：

1. **触发是否可被一句话描述？** 如果"什么时候该用它"要写半页，说明场景太模糊，模型会乱触发或漏触发。
2. **是否需要携带额外上下文/脚本/数据？** 纯提示词用 CLAUDE.md 或 slash command 更轻；需要带参考文档、可执行脚本、结构化数据时，Skill 才划算。
3. **是否会被反复使用？** 一次性任务不值得封装成本。

SQL 优化完美命中：触发清晰（"优化/调优/慢查询/加索引"）、需要携带反模式知识库和静态分析脚本、且在业务里高频复用。这三条都满足，才往下走。

## 第二步：理解 Skill 的三层目录与渐进披露架构

Claude Code 在三个位置自动发现 Skill：

| 位置 | 作用域 | 典型用途 |
|------|--------|----------|
| `.claude/skills/<name>/` | 当前项目 | 团队共享，随仓库分发 |
| `~/.claude/skills/<name>/` | 个人全局 | 跨项目个人能力 |
| `~/.claude/plugins/<plugin>/skills/<name>/` | 插件分发 | 打包给他人安装 |

关键机制是**渐进披露**：会话开始时，模型并不会读入每个 Skill 的全文，而是只看它们的 `name` + `description`（这是"货架标签"）。只有当任务命中某个 description，模型才会按需读取 `SKILL.md` 正文，正文里再指向更深层的 `references/`、`scripts/`、`examples/`。这样 50 个 Skill 也不会撑爆上下文窗口。

本例的目录结构如下：

```
.claude/skills/sql-optimizer/
├── SKILL.md                 # 入口：精炼的工作流 + 触发描述
├── references/
│   ├── anti-patterns.md     # 反模式知识库（按需加载）
│   └── index-tuning.md      # 索引调优手册（按需加载）
├── scripts/
│   └── analyze_sql.py       # 静态嗅探脚本
└── examples/
    └── before-after.md      # 标准化案例库
```

## 第三步：用 skill-creator 脚手架生成骨架

Claude Code 自带 `skill-creator` 能力，可以直接交互式生成骨架，避免手敲目录和漏掉字段。在交互模式下输入：

```
/skill-creator
```

按提示回答 Skill 名称（`sql-optimizer`）、用途、是否需要脚本。它会生成最小骨架。你也可以直接手动创建，下面是手写路径——更利于理解每一处字段的含义。

先建目录：

```bash
mkdir -p .claude/skills/sql-optimizer/{references,scripts,examples}
```

## 第四步：写好 description——这是 Skill 的"命门"

整个 Skill 最重要的一行不是正文，而是 frontmatter 里的 `description`。模型在每轮对话里都要扫一遍所有 Skill 的 description 来判断要不要激活它，因此 description 必须自带**触发词、场景、产出物**三要素。

`SKILL.md` 的开头：

```yaml
---
name: sql-optimizer
description: Reviews and optimizes SQL queries (SELECT/JOIN/subquery). Use PROACTIVELY when the user asks to optimize, tune, speed up, or refactor SQL, detect slow queries, suggest indexes, or explain query performance. Produces an annotated original, a rewritten query, index DDL, and an expected-impact estimate. Skip for schema/DDL design and ORM-only questions.
allowed-tools: Bash, Read, Edit, Write
---
```

几个实战要点：

- **`name` 必须 kebab-case、全小写、无空格**，否则发现机制会忽略它。
- description 里**显式写出触发动词**（optimize、tune、speed up、refactor）。模型对动词比对名词敏感。
- 用 `Use PROACTIVELY when...` 句式告诉模型可以主动触发，而不是等用户点名。
- **反向声明"什么时候不用"**（`Skip for...`）。这是被严重低估的技巧——明确排除相邻场景，能显著降低误触发。
- `allowed-tools` 把能力收敛到 `Bash, Read, Edit, Write`。一个只做 SQL 分析的 Skill 不需要触达所有工具，**最小权限原则既安全又能减少误操作**。

常见问题：**Skill 写好了但从不被触发**。十有八九是 description 写成了功能说明（"这是一个SQL优化工具"）而非触发条件（"当用户要优化SQL时用我"）。模型判断的是"现在该不该用你"，不是"你是干嘛的"。

## 第五步：写正文——精炼是美德，细节下沉到 references

正文要短，把"具体怎么做"的判断逻辑讲清楚，把"知识本身"下沉到按需文件。`SKILL.md` 正文：

```markdown
# SQL Optimizer

You are a database performance specialist. Optimize SQL the user provides.

## Workflow
1. If the target RDBMS (MySQL/Postgres/etc.) is unclear, ASK once before optimizing.
2. Run the static sniffer:
   `python3 scripts/analyze_sql.py "<query>"`
   to get a ranked smell report.
3. Branch on findings:
   - Indexing issues (missing WHERE, wildcard LIKE, sort) → read `references/index-tuning.md`.
   - Anti-patterns (SELECT *, NOT IN, function on column) → read `references/anti-patterns.md`.
   - Both → read both.
4. Output exactly four sections:
   a. **Annotated original** — mark each smell inline.
   b. **Rewritten query** — runnable, idiomatic for the RDBMS.
   c. **Index DDL** — `CREATE INDEX` statements, if any.
   d. **Expected impact** — one sentence, qualitatively ranked Low/Med/High.

## Rules
- Never guess the RDBMS.
- Always state WHY each change helps — no silent rewrites.
- Prefer covering indexes over single-column indexes when the SELECT list is small.
```

注意正文里出现了对 `references/*.md` 和 `scripts/*.sql` 的相对路径引用。**只有当正文被读取后、模型真的需要这些文件时，它们才会被加载**——这就是渐进披露在工程上的落点。一个 2000 字的反模式手册因此不会无谓地占满上下文。

## 第六步：封装可执行脚本，把确定性逻辑外置

LLM 不擅长的事情（精确计数、正则匹配、确定性规则）应当外置成脚本。`scripts/analyze_sql.py` 用纯启发式规则给查询打"气味"标签：

```python
#!/usr/bin/env python3
"""Static smell detector. Usage: analyze_sql.py "<sql>" """
import re, sys

def analyze(sql):
    s = sql.lower()
    out = []
    if "select *" in s:
        out.append(("HIGH", "SELECT *", "Pulls unneeded columns; blocks covering indexes."))
    if s.count("join") >= 3:
        out.append(("MED", ">=3 JOINs", "Verify join keys; risk of fan-out."))
    if re.search(r"like\s+'%", s):
        out.append(("HIGH", "Leading-wildcard LIKE", "Defeats B-tree index usage."))
    if not re.search(r"\bwhere\b", s) and re.search(r"\bfrom\b", s):
        out.append(("HIGH", "No WHERE", "Full table scan risk on large tables."))
    if re.search(r"order by", s) and "limit" not in s:
        out.append(("MED", "ORDER BY without LIMIT", "Sorts the entire result set."))
    if re.search(r"not in", s):
        out.append(("MED", "NOT IN", "Three-valued logic; prefer NOT EXISTS."))
    return out

if __name__ == "__main__":
    sql = sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()
    for sev, name, note in analyze(sql):
        print(f"[{sev}] {name} — {note}")
```

赋可执行权限：

```bash
chmod +x .claude/skills/sql-optimizer/scripts/analyze_sql.py
```

**预期结果**：当用户给出 `SELECT * FROM orders WHERE name LIKE '%phone%' ORDER BY created_at`，脚本输出三行：

```
[HIGH] SELECT * — Pulls unneeded columns; blocks covering indexes.
[HIGH] Leading-wildcard LIKE — Defeats B-tree index usage.
[MED]  ORDER BY without LIMIT — Sorts the entire result set.
```

模型拿到这份确定性报告后，再去 `references/` 里查应对策略，比纯靠它"想"要稳得多。常见问题：**脚本路径写死绝对路径**。务必用相对路径 `scripts/analyze_sql.py`，因为 Skill 可能在不同机器、不同项目根被加载，绝对路径一搬就断。

## 第七步：references 文件——知识库就是数据，不是散文

`references/anti-patterns.md` 要写成**结构化、可检索**的条目，而不是博客体。模板：

```markdown
# SQL Anti-Patterns

## SELECT *
- **Symptom**: fetching all columns.
- **Harm**: blocks covering indexes; wastes I/O; breaks refactors.
- **Fix**: project only needed columns.

## Function on indexed column in WHERE
- **Symptom**: `WHERE DATE(created_at) = '2026-06-15'`.
- **Harm**: wraps the column → index ignored → full scan.
- **Fix**: sargable form `WHERE created_at >= '...' AND created_at < '...'`.
```

`references/index-tuning.md` 同理，按"症状→危害→修法"三段式写。这种结构让模型能精确引用条目，也方便人类维护。**把团队的真实事故案例塞进 `examples/before-after.md`**，这是 Skill 区别于通用知识库的最大价值——它承载了你们团队的特定经验。

## 第八步：本地联调与 eval 评测

写完先在交互模式下手工冒烟。键入：

```
帮我优化这条SQL：SELECT * FROM orders WHERE customer_name LIKE '%张' ORDER BY amount
```

预期：Claude 自动激活 `sql-optimizer`，先问 RDBMS（或你已在 CLAUDE.md 声明则跳过），运行嗅探脚本，加载对应 reference，输出四段式结果。

**触发了不代表好用**。用 `skill-creator` 的 eval 能力做量化评测：准备一组正样本（"优化这条慢查询"）和负样本（"帮我设计订单表结构"），统计激活率与误激活率。目标：正样本命中 ≥ 90%，负样本误触发 ≤ 10%。若负样本误触发，回第四步收紧 description 的 `Skip for...`；若正样本漏触发，补充同义动词到 description。

## 实战案例：把一个真实慢查询变成四段式交付

输入用户问题：

> 我们这条报表查询要 8 秒，能不能优化？
> `SELECT * FROM orders o JOIN items i ON o.id = i.order_id JOIN products p ON i.pid = p.id WHERE p.category = 'book'`

Claude 激活 Skill 后，先确认是 MySQL，跑嗅探脚本得到 `[HIGH] SELECT *` 与 `[MED] >=3 JOINs`，加载 `anti-patterns.md` 与 `index-tuning.md`，最终交付：

1. **标注原文**：圈出 `SELECT *`、三个 JOIN 的连接键。
2. **改写**：投影必要列，并在 `products(category, id)` 上加索引推动谓词下推。
3. **索引 DDL**：`CREATE INDEX idx_products_category ON products(category, id);`
4. **预期收益**：HIGH——把全表扫描+大结果集排序，收敛为索引范围扫描，预计从 8s 降到亚秒级。

整个过程模型没有"幻觉"反模式，因为判定来自脚本；优化建议来自团队沉淀的 reference，可追溯、可复用。

## 工作流程图

```mermaid
flowchart TD
    A[用户提问] --> B{扫描所有 Skill 的<br/>name+description}
    B -->|命中 sql-optimizer| C[加载 SKILL.md 正文]
    B -->|未命中| Z[按普通对话处理]
    C --> D[确认 RDBMS]
    D --> E[运行 analyze_sql.py<br/>得到确定性嗅探报告]
    E --> F{嗅探结果分流}
    F -->|索引类问题| G[按需读取 index-tuning.md]
    F -->|反模式类问题| H[按需读取 anti-patterns.md]
    F -->|两者皆有| G
    G --> I[产出四段式交付]
    H --> I
    I --> J[标注原文 / 改写 / DDL / 收益]
```

核心在于 **B 处只看 description（货架层）**，而 **C→G→H 是按需展开（渐进披露层）**。没有命中的 Skill 零成本，命中后才逐层加载资源。

## 延伸阅读

- **官方 Skills 文档**：`code.claude.com/docs/en/skills` —— frontmatter 字段、发现机制的权威定义。
- **skill-creator 能力**：用 `/skill-creator` 生成骨架并跑 eval，是评测触发精度的标准工具。
- **渐进披露原则**：把知识按"标签 → 正文 → references"三层组织，是 Skill 与普通提示词的根本分野。
- **allowed-tools 收敛**：每个 Skill 只授予必需工具，是团队级安全实践。
- 进阶方向：把 `sql-optimizer` 升级为可调用子 Agent（多 Skill 编排），或与一个真实数据库 MCP 工具结合，让嗅探脚本拿到 `EXPLAIN` 真实执行计划。

## 训练营适用性评估

- **适合类型**：企业内训"AI 工程化"方向、研发团队效能提升营、后端/DBA 工程师进阶营。
- **教学时长**：建议 3 小时（1 小时讲架构与 description 工程，1 小时动手搭建，1 小时做 eval 调优）。
- **难度定位**：中级偏实践。学员需已掌握 Claude Code 基础交互。
- **可扩展作业**：让学员各自封装一个本团队的领域 Skill（如日志分析、配置审查），互评触发精度，把训练营产出沉淀为团队技能库。

## 参考来源

1. [Extend Claude with skills — Claude Code Docs](https://code.claude.com/docs/en/skills) — 官方 Skills 文档，定义 SKILL.md 结构、frontmatter 字段与发现机制。
2. [Claude Code Skills 2026 — Progressive Disclosure and How to Standardise Workflow](https://anhtu.dev/claude-code-skills-2026-progressive-disclosure-and-how-to-standardise-workflow-for-engineering-teams-1062) — 三层渐进披露架构的工程化深度解读。
3. [The Complete Guide to Creating and Using Claude Skills 2026](https://aifordevelopers.substack.com/p/the-complete-guide-to-creating-and) — 从规划到可用 SKILL.md 的完整实践指南。
4. [Claude Skills Explained: Use Custom Skills on Claude Code](https://www.analyticsvidhya.com/blog/2026/03/claude-skills-custom-skills-on-claude-code/) — description 触发机制与构建流程的图文化讲解。
5. [How to Create a Claude Code Skill: Hands-On Guide](https://readysolutions.ai/blog/2026-04-29-how-to-create-claude-or-claude-code-skill-hands-on-guide/) — 面向首个 Skill 的实操手册，含目录组织与调试技巧。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
