本教程以"SQL查询优化助手"为载体,完整演示从需求拆解到评测上线的 Claude Code 自定义 Skill 开发全流程。你将掌握 SKILL.md 的 frontmatter 工程化、渐进披露(Progressive Disclosure)的分层落地、可执行脚本的封装与权限收敛、以及用 eval 量化触发精度。适合已跑通过 Claude Code 基础用法、希望把团队经验沉淀为可复用能力的开发者和 Tech Lead。
/ 命令git 的开发机(示例脚本用 Python)很多人上手就建 SKILL.md,这是最常见的浪费。Skill 不是"把提示词存起来",而是一段可被模型在恰当场景自动调用的、带资源约束的能力封装。在动手前,用三个问题自检:
SQL 优化完美命中:触发清晰("优化/调优/慢查询/加索引")、需要携带反模式知识库和静态分析脚本、且在业务里高频复用。这三条都满足,才往下走。
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 # 标准化案例库
Claude Code 自带 skill-creator 能力,可以直接交互式生成骨架,避免手敲目录和漏掉字段。在交互模式下输入:
/skill-creator
按提示回答 Skill 名称(sql-optimizer)、用途、是否需要脚本。它会生成最小骨架。你也可以直接手动创建,下面是手写路径——更利于理解每一处字段的含义。
先建目录:
mkdir -p .claude/skills/sql-optimizer/{references,scripts,examples}
整个 Skill 最重要的一行不是正文,而是 frontmatter 里的 description。模型在每轮对话里都要扫一遍所有 Skill 的 description 来判断要不要激活它,因此 description 必须自带触发词、场景、产出物三要素。
SKILL.md 的开头:
---
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、全小写、无空格,否则发现机制会忽略它。Use PROACTIVELY when... 句式告诉模型可以主动触发,而不是等用户点名。Skip for...)。这是被严重低估的技巧——明确排除相邻场景,能显著降低误触发。allowed-tools 把能力收敛到 Bash, Read, Edit, Write。一个只做 SQL 分析的 Skill 不需要触达所有工具,最小权限原则既安全又能减少误操作。常见问题:Skill 写好了但从不被触发。十有八九是 description 写成了功能说明("这是一个SQL优化工具")而非触发条件("当用户要优化SQL时用我")。模型判断的是"现在该不该用你",不是"你是干嘛的"。
正文要短,把"具体怎么做"的判断逻辑讲清楚,把"知识本身"下沉到按需文件。SKILL.md 正文:
# 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 用纯启发式规则给查询打"气味"标签:
#!/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}")
赋可执行权限:
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/anti-patterns.md 要写成结构化、可检索的条目,而不是博客体。模板:
# 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 区别于通用知识库的最大价值——它承载了你们团队的特定经验。
写完先在交互模式下手工冒烟。键入:
帮我优化这条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,最终交付:
SELECT *、三个 JOIN 的连接键。products(category, id) 上加索引推动谓词下推。CREATE INDEX idx_products_category ON products(category, id);整个过程模型没有"幻觉"反模式,因为判定来自脚本;优化建议来自团队沉淀的 reference,可追溯、可复用。
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 零成本,命中后才逐层加载资源。
code.claude.com/docs/en/skills —— frontmatter 字段、发现机制的权威定义。/skill-creator 生成骨架并跑 eval,是评测触发精度的标准工具。sql-optimizer 升级为可调用子 Agent(多 Skill 编排),或与一个真实数据库 MCP 工具结合,让嗅探脚本拿到 EXPLAIN 真实执行计划。[!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 等场景全覆盖。
