站内精选

一句话结论

把 3 条慢 SQL 连同表结构、执行计划丢给 AI,让它逐条判断索引该不该加、加在哪,产出一张能照着改的排查结论表。

这篇解决什么问题

慢查询堆起来的时候,最常见的处理是凭经验随手加索引,加完发现根本没走,或者写反而变慢了。我碰到的情况往往是三条 SQL 卡在同一个库上,谁也不敢先动第一刀。

适用:手上已经有慢查询日志,能拿到建表语句,想让 AI 帮你把索引方案过一遍。不适用:SQL 本身写法有问题,比如 SELECT *、在字段上套函数、隐式类型转换,那种得先改写,加索引是白加。

开始前要准备什么

  • Claude 网页版,免费额度跑几条 SQL 的问答够用
  • Cursor 可选,表结构在项目里时直接在编辑器里问
  • 3 条慢 SQL 原文,最好带上各自的平均耗时
  • 涉及表的建表语句,SHOW CREATE TABLE 直接粘
  • 表的大致行数和查询频率,量级就行
  • 耗时:整理材料 10 分钟以内,对话 15 分钟上下

具体怎么做

第 1 步 · 把材料备齐成一段文本

别上来就问「这条 SQL 怎么优化」,先备料。我习惯按 SQL 原文、平均耗时、建表语句、大概行数四块凑成一段,AI 读起来比散着贴准得多。库名表名换成化名,真实业务字段别原样放出去。

你先当一名有十年经验的 MySQL 性能优化工程师,这一轮先不要给建议。下面是我从慢查询日志里捞出来的 3 条 SQL,以及涉及表的建表语句。请逐条做三件事:1)列出这条 SQL 的过滤条件字段、排序字段、返回列;2)判断它可能命中哪些已有索引;3)指出我提供的信息里还缺什么,比如数据分布、字段区分度、行数。输出用编号列表,每条 SQL 一节。
【SQL 1】
SELECT id, user_id, amount, created_at FROM t_order WHERE user_id = 10086 AND status = 1 ORDER BY created_at DESC LIMIT 20;
平均耗时:1 秒左右
【SQL 2】
SELECT o.id, o.amount, u.nickname FROM t_order o JOIN t_user u ON o.user_id = u.id WHERE o.created_at >= ‘2024-05-01’ AND u.city = ‘杭州’;
平均耗时:2 秒左右
【SQL 3】
SELECT COUNT(*) FROM t_order WHERE status = 1 AND created_at >= ‘2024-05-01’;
平均耗时:3 秒左右
【表结构】
CREATE TABLE t_order (
id bigint NOT NULL AUTO_INCREMENT,
user_id bigint NOT NULL,
status tinyint NOT NULL DEFAULT 0,
amount decimal(10,2) NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (id),
KEY idx_user (user_id)
) ENGINE=InnoDB;
CREATE TABLE t_user (
id bigint NOT NULL AUTO_INCREMENT,
nickname varchar(64) NOT NULL,
city varchar(32) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
【数据量级】t_order 约几十万行,每天新增几千行;t_user 约几万行。

预期产出:一份信息清单,能看出哪些字段 AI 还需要你补,比如 status 到底有几个取值。这一步看着啰嗦,但后面判断准不准全靠它。

第 2 步 · 先判该不该加,别急着要 DDL

很多人直接让 AI 给建索引语句,结果它硬凑。我在实操中发现,先让它明确表态「该不该加」,命中率明显高,尤其是那条 COUNT 的 SQL,它经常被你问出「其实该加缓存或者改统计方式」。

基于上一轮的输出,现在逐条判断这三条 SQL 要不要新增索引。每一条按这个格式回答:
– 结论:需要新增 / 不需要,改写法更划算 / 需要但收益有限
– 依据:耗时发生在哪一步,回表、排序还是全表扫,说清楚为什么
– 候选索引:字段顺序写出来,例如 (user_id, status, created_at)
– 风险:写放大、区分度低、和已有索引重复,适用的说
如果某条 SQL 的过滤字段区分度很低,比如 status 只有几个取值,要明确说出来,不要硬凑一个索引交差。

预期产出:三条 SQL 各自的判断和依据,通常能砍掉一两条不该加的,剩下的才是真正要动手的。

第 3 步 · 要到索引定义和预期计划变化

这一步最容易被跳过。只拿一条 CREATE INDEX 没什么用,你得知道加完之后 EXPLAIN 里该看到什么,不然上线了也不知道成没成。

把上一轮判定「需要新增」的索引写成可以直接执行的 DDL,MySQL 8.0 语法。每条 DDL 后面补三行说明:1)最左前缀怎么匹配这几条 SQL;2)加完之后 EXPLAIN 里的 type、key、rows、Extra 应该出现什么变化;3)按当前行数估算这条索引大概占多少空间。不要给功能重复的索引,如果两个候选只差一个字段,合并成一个并说明理由。

预期产出:一到两条 DDL,配一份「加完之后应该看到什么」的对照,拿去测试库跑 EXPLAIN 正好能验证。

第 4 步 · 收成一张排查结论表

对话到这里信息已经很散,必须收口。我固定用七个列,多一列都嫌累赘,好处是贴进周报或者工单里,别人一眼能看完。

把前面的结论收成一张表,用 markdown 表格,列固定为:SQL 编号 / 主要耗时点 / 现有索引是否够用 / 建议索引 / 预估收益 / 上线风险 / 优先级。优先级用 P0 到 P2 三档。表格下面补两句话:哪条建议先上,哪条建议先观察一周再说。整张表要能直接贴进周报。

预期产出:一张排查结论表,这就是你要交付的东西,之后开会、提单、排期都拿它说话。

第 5 步 · 反过来让它挑自己的刺

AI 给的方案第一版往往偏乐观,尤其是不提写放大的代价。换个角色让它自审,能筛掉一批「加了反而更慢」的建议。

现在换一个角色:你是负责这次上线的 DBA,要审核上面这套索引方案。请逐条挑刺:1)有没有和现有索引功能重叠的;2)有没有可能让某条写多读少的 SQL 变慢;3)有没有哪条建议其实是在给一个本该改写的 SQL 打补丁。每条挑刺给出理由和替代做法。最后给一句结论:这套方案能不能直接上,还是需要先做哪一步验证。

预期产出:一份风险清单,加上一句能不能上的判断。我一般会把它附在结论表后面,评审的时候省很多口舌。

实测记录

环节 实际情况
整理材料 约 10 分钟,三条 SQL 两张表
五轮对话 约 15 分钟,第三步返工过一次
和手工对比 手工翻执行计划要小半天,结论大体一致
返工原因 第一轮没给行数,AI 建议了个区分度很低的索引

成本上没什么可说的,用的都是免费额度。真正省下来的不是写 DDL 那几分钟,是逼着你把过滤条件、区分度、写放大这几件事一次想清楚。手工做也能做,但容易漏,尤其是已有索引重叠这种情况。

最容易错的 3 个地方

  1. 只贴 SQL 不贴表结构。AI 猜不到字段区分度,会给你一个看着合理实则没用的索引。纠正:建表语句和大概行数必须一起给。
  2. 让它一次给所有索引。结果冒出好几个功能重叠的单列索引,线上白占空间。纠正:要求合并同功能候选,并说明最左前缀。
  3. DDL 拿到就直接上生产。跳过 EXPLAIN 验证,出问题才回头查。纠正:先在测试库对比执行计划,再让它以 DBA 角色自审一轮。

可复用的东西

整套流程就是五段提示词:备料清单、该不该加的判断、DDL 与计划预期、结论表、DBA 自审。顺序别乱,尤其是判断和 DDL 一定要分开问,混在一起 AI 会直接跳到结论。

材料那段可以存成模板,把表名和字段换掉就能复用。表结构如果就在项目里,用 Cursor 打开对应的 migration 文件,省掉来回复制这一步。

说到底,AI 在这件事里干的是「逼你把信息补齐」和「帮你把话说全」,索引加不加、先加哪条,还是得你看着执行计划拍板。

你手上那几条慢 SQL,卡住的到底是过滤字段没索引,还是排序惹的祸?

常见问题解答

表结构和 SQL 里带真实业务字段,直接贴给 AI 安全吗?

库名、表名、字段值建议换成化名,结构保留就行。行数和耗时给个量级也够 AI 判断,不影响结论。

AI 给的索引建议和 DBA 意见不一致怎么办?

拿执行计划说话。让 AI 把「加完之后 EXPLAIN 应该看到什么」写出来,去测试库跑一遍,对不上就以实测为准。

只有一条慢 SQL,这套流程还用走吗?

可以压缩成三步:备料、判断该不该加、要 DDL 和计划预期。结论表那步对单条意义不大,但 DBA 自审建议留着。

小程序阅读免费
微信扫码进入小程序,按岗位找 AI 实操步骤
微信扫码进小程序
按岗位找 AI 实操步骤 · 提示词可收藏

发表回复

后才能评论