前言

后端项目做到一定阶段,接口变慢几乎是绕不开的问题。

有时候本地测试很快,到了测试环境或者线上环境就开始变慢;有时候接口本身没有复杂逻辑,但一查日志发现某条 SQL 执行了几百毫秒甚至几秒;还有些情况更麻烦,单次查询不慢,并发一上来整体响应时间就明显抖动。

这类问题如果只靠人工看 SQL、猜索引、翻执行计划,效率并不高。尤其是业务表字段多、关联表多、条件分支多的时候,很容易漏掉关键点。

ChatGPT 5.5 这类大模型在这里比较适合做一件事:辅助整理慢 SQL 排查思路。

它不能替代数据库执行计划,也不能直接告诉你“加这个索引一定好”。但它可以帮你把 SQL、表结构、查询条件、执行计划和现象整理成一条比较清晰的排查路径,减少无效尝试。

本文以一个常见的订单查询接口为例,看看如何用 ChatGPT 5.5 辅助分析慢 SQL 问题。


一、问题场景:订单列表接口变慢

假设有一个订单列表接口:

http

GET /api/order/list

接口用于后台管理系统查询订单,支持以下筛选条件:

  • 用户 ID;
  • 订单状态;
  • 创建时间范围;
  • 关键词;
  • 分页参数。

最近测试反馈:订单数据量上来之后,这个接口明显变慢。

接口日志中可以看到:

text

2026-01-18 14:21:36.128 INFO  [order-service] GET /api/order/list cost=2860ms, pageNo=1, pageSize=20

对应 SQL 大概如下:

sql

SELECT    o.id,    o.order_no,    o.user_id,    o.status,    o.amount,    o.create_time,    u.nicknameFROM t_order oLEFT JOIN t_user u ON o.user_id = u.idWHERE 1 = 1  AND o.status = 1  AND o.create_time >= '2026-01-01 00:00:00'  AND o.create_time <= '2026-01-18 23:59:59'  AND (      o.order_no LIKE '%202601%'      OR u.nickname LIKE '%张%'  )ORDER BY o.create_time DESCLIMIT 0, 20;

订单表结构简化如下:

sql

CREATE TABLE t_order (    id BIGINT PRIMARY KEY AUTO_INCREMENT,    order_no VARCHAR(64) NOT NULL,    user_id BIGINT NOT NULL,    status TINYINT NOT NULL,    amount DECIMAL(10, 2) NOT NULL,    create_time DATETIME NOT NULL,    update_time DATETIME NOT NULL);

用户表结构简化如下:

sql

CREATE TABLE t_user (    id BIGINT PRIMARY KEY AUTO_INCREMENT,    nickname VARCHAR(64) NOT NULL,    phone VARCHAR(32),    create_time DATETIME NOT NULL);

已有索引:

sql

CREATE INDEX idx_order_user_id ON t_order(user_id);CREATE INDEX idx_order_status ON t_order(status);CREATE INDEX idx_order_create_time ON t_order(create_time);

看起来该有的索引都有,但接口还是慢。
这种情况下,直接问“这条 SQL 怎么优化”往往会得到一些比较泛的建议,比如加索引、减少 LIKE、避免 SELECT *。

更好的方式是让 ChatGPT 5.5 先帮我们整理问题。


二、先让 ChatGPT 5.5 区分事实和猜测

可以这样提问:

text

你是一名 MySQL 慢 SQL 排查助手。下面是一条订单列表查询 SQL、表结构和已有索引。
请帮我完成:1. 只基于已给信息整理已确认事实;2. 分析可能导致慢查询的因素;3. 不要直接给最终结论;4. 按优先级给出后续需要补充的信息;5. 输出适合研发排查记录使用。
【SQL】粘贴 SQL
【表结构】粘贴表结构
【已有索引】粘贴索引

它输出的内容通常会比较接近下面这样:

markdown

## 已确认事实
1. 查询主表为 `t_order`,并通过 `user_id` 左连接 `t_user`。2. 查询条件包含 `status`、`create_time` 和关键词模糊匹配。3. 结果按 `o.create_time DESC` 排序,并使用 `LIMIT 0, 20` 分页。4. `t_order` 上已有单列索引:`user_id`、`status`、`create_time`。5. 关键词查询中存在 `LIKE '%xxx%'` 的写法。6. 查询字段中包含用户昵称,需要关联用户表。
## 可能影响性能的因素
1. `LIKE '%202601%'` 和 `LIKE '%张%'` 前置通配符可能导致索引失效。2. `OR` 条件横跨订单表和用户表,可能增加优化器选择难度。3. `status`、`create_time` 分别有单列索引,但不一定能很好支持组合过滤和排序。4. `ORDER BY create_time DESC LIMIT 20` 如果不能走合适索引,可能产生 filesort。5. 关联用户表后再做昵称模糊匹配,可能扩大扫描范围。6. 如果订单表数据量较大,单列索引选择性不足会导致扫描行数较多。
## 需要补充的信息
1. `EXPLAIN` 执行计划。2. `t_order` 和 `t_user` 的数据量。3. `status = 1` 的数据占比。4. 时间范围内订单数量。5. 关键词条件是否高频使用。6. 是否必须支持订单号和昵称同时模糊搜索。7. 是否有深分页场景。

这个结果的价值在于:它没有一上来就说“加索引”,而是先把可能影响 SQL 的因素拆出来。

慢 SQL 排查时,最忌讳的就是看到慢就盲目加索引。
加错索引不仅没效果,还可能影响写入性能。


三、把 EXPLAIN 结果交给模型分析

接下来我们补充执行计划。

假设执行:

sql

EXPLAINSELECT    o.id,    o.order_no,    o.user_id,    o.status,    o.amount,    o.create_time,    u.nicknameFROM t_order oLEFT JOIN t_user u ON o.user_id = u.idWHERE 1 = 1  AND o.status = 1  AND o.create_time >= '2026-01-01 00:00:00'  AND o.create_time <= '2026-01-18 23:59:59'  AND (      o.order_no LIKE '%202601%'      OR u.nickname LIKE '%张%'  )ORDER BY o.create_time DESCLIMIT 0, 20;

得到简化后的结果:

text

id: 1select_type: SIMPLEtable: otype: rangepossible_keys: idx_order_status,idx_order_create_timekey: idx_order_create_timerows: 180000Extra: Using index condition; Using where
id: 1select_type: SIMPLEtable: utype: eq_refpossible_keys: PRIMARYkey: PRIMARYrows: 1Extra: Using where

可以继续问 ChatGPT 5.5:

text

下面是这条 SQL 的 EXPLAIN 结果,请帮我分析。
要求:1. 解释每个关键信息代表什么;2. 判断当前执行计划可能的问题;3. 给出下一步验证方向;4. 不要直接假设某个索引一定有效。

比较合理的分析会是:

markdown

## 执行计划解读
1. 主表 `t_order` 使用了 `idx_order_create_time` 索引。2. 访问类型为 `range`,说明根据时间范围做了范围扫描。3. 预计扫描行数为 180000,扫描量较大。4. `Extra` 中出现 `Using where`,说明索引扫描后仍需进一步过滤。5. 用户表 `t_user` 通过主键关联,访问类型为 `eq_ref`,单次关联成本较低。6. 当前主要压力可能集中在订单表扫描和过滤阶段。
## 可能问题
1. 时间范围内订单数量较多,导致 `idx_order_create_time` 扫描行数较大。2. `status = 1` 没有和 `create_time` 形成更有效的组合过滤。3. `LIKE '%xxx%'` 条件无法有效利用普通 BTree 索引。4. `OR` 条件涉及两张表,可能导致过滤效率下降。5. 如果排序无法完全利用索引,可能存在额外排序成本。
## 下一步验证
1. 查看 `status = 1` 的数据占比。2. 分别去掉关键词条件、去掉用户昵称条件测试耗时。3. 测试组合索引 `(status, create_time)` 的效果。4. 查看是否存在 `Using filesort`。5. 使用 `EXPLAIN ANALYZE` 查看真实耗时和真实扫描行数。

这里模型给出的不是最终答案,而是帮助我们把执行计划翻译成更容易理解的排查步骤。


四、常见问题一:单列索引不等于查询就快

当前订单表已有三个索引:

sql

CREATE INDEX idx_order_user_id ON t_order(user_id);CREATE INDEX idx_order_status ON t_order(status);CREATE INDEX idx_order_create_time ON t_order(create_time);

很多人看到这里会觉得:状态有索引,时间有索引,用户 ID 也有索引,应该够用了。

但这条 SQL 的核心条件是:

sql

WHERE o.status = 1  AND o.create_time >= ...  AND o.create_time <= ...ORDER BY o.create_time DESCLIMIT 0, 20

这种查询往往更适合考虑组合索引,例如:

sql

CREATE INDEX idx_order_status_create_timeON t_order(status, create_time);

可以让 ChatGPT 5.5 帮你分析为什么这个组合索引可能有用:

text

对于下面这个查询条件:status = 1create_time between ...order by create_time desclimit 20
请解释为什么组合索引 (status, create_time) 可能比单列索引更适合。

输出可以整理为:

markdown

组合索引 `(status, create_time)` 可能更适合的原因:
1. `status` 是等值查询,可以作为组合索引第一列。2. `create_time` 是范围查询,可以在同一个索引中继续缩小扫描范围。3. 查询需要按照 `create_time` 排序,如果索引顺序匹配,可能减少额外排序成本。4. 相比只使用 `idx_order_create_time`,组合索引可以先过滤状态,再扫描时间范围。5. 如果 `status = 1` 的数据占比不是特别高,组合索引可以明显减少扫描行数。

不过需要注意,这里用了“可能”。
因为索引是否有效,还取决于数据分布。

如果 status = 1 占全表 95%,那么这个字段的过滤效果就很弱。
这时候组合索引仍可能有帮助,但效果未必明显。


五、常见问题二:LIKE '%关键词%' 很难走普通索引

SQL 中有两个模糊查询:

sql

o.order_no LIKE '%202601%'OR u.nickname LIKE '%张%'

这种前后都有 % 的写法,对普通 BTree 索引非常不友好。

如果业务允许,可以把订单号查询改成前缀匹配:

sql

o.order_no LIKE '202601%'

这样才有机会利用订单号索引:

sql

CREATE INDEX idx_order_no ON t_order(order_no);

但如果必须支持任意位置模糊匹配,比如:

sql

LIKE '%202601%'

那普通索引基本帮不上太多。

可以让 ChatGPT 5.5 继续帮我们拆方案:

text

订单号和用户昵称都需要支持关键词搜索,现在使用 LIKE '%keyword%'。请给出几种优化思路,并说明适用条件和缺点。

可能得到这样的结果:

markdown

## 方案一:改为前缀匹配
示例:
```sqlo.order_no LIKE '202601%'

适用条件:

  • 订单号本身有明确前缀规则;
  • 用户搜索习惯可以接受从开头匹配。

优点:

  • 可以利用普通 BTree 索引;
  • 改造成本低。

缺点:

  • 不支持任意位置匹配。

方案二:拆分搜索逻辑

订单号搜索和昵称搜索分开处理:

  • 如果关键词像订单号,只查订单表;
  • 如果关键词像昵称,再关联用户表;
  • 避免每次都同时 OR 两个字段。

优点:

  • 减少无效关联和扫描;
  • 查询路径更清晰。

缺点:

  • 需要业务规则判断关键词类型。

方案三:引入搜索引擎

如 Elasticsearch、OpenSearch 等。

适用条件:

  • 搜索需求复杂;
  • 数据量较大;
  • 需要分词、模糊搜索、排序等能力。

优点:

  • 搜索能力强;
  • 更适合复杂关键词查询。

缺点:

  • 引入额外组件;
  • 存在数据同步和一致性问题。

方案四:建立冗余搜索字段

在订单表中冗余用户昵称或搜索关键字段,减少 join 查询。

优点:

  • 查询链路简单;
  • 对后台列表查询比较友好。

缺点:

  • 数据更新时需要同步;
  • 存在冗余字段一致性问题。

这个输出就比较适合作为方案讨论的基础。
---
## 六、常见问题三:OR 条件可能让优化变复杂
原 SQL 中的关键词条件是:
```sqlAND (    o.order_no LIKE '%202601%'    OR u.nickname LIKE '%张%')

这里有两个特点:

  1. OR 连接了两个条件;
  2. 两个条件还分别位于不同表。

这种写法对优化器并不友好。
如果数据量不大问题不明显,但数据量上来后,很容易变慢。

一种常见改法是根据关键词类型拆 SQL。

例如订单号有固定格式:

text

202601180001

那么当关键词符合订单号格式时,只查订单号:

sql

SELECT    o.id,    o.order_no,    o.user_id,    o.status,    o.amount,    o.create_time,    u.nicknameFROM t_order oLEFT JOIN t_user u ON o.user_id = u.idWHERE o.status = 1  AND o.create_time >= '2026-01-01 00:00:00'  AND o.create_time <= '2026-01-18 23:59:59'  AND o.order_no LIKE '202601%'ORDER BY o.create_time DESCLIMIT 0, 20;

如果关键词明显是昵称,再走用户昵称查询路径。

也可以先查用户 ID:

sql

SELECT idFROM t_userWHERE nickname LIKE '%张%';

再查订单:

sql

SELECT    o.id,    o.order_no,    o.user_id,    o.status,    o.amount,    o.create_timeFROM t_order oWHERE o.user_id IN (...)  AND o.status = 1  AND o.create_time >= '2026-01-01 00:00:00'  AND o.create_time <= '2026-01-18 23:59:59'ORDER BY o.create_time DESCLIMIT 0, 20;

当然,这种方式也不是一定更快。
如果昵称匹配出来的用户很多,IN 列表也可能变大。最终还是要靠执行计划和真实压测验证。


七、让 ChatGPT 5.5 生成验证清单

慢 SQL 优化最重要的是验证,而不是凭感觉改。

可以继续这样问:

text

针对这条订单列表慢 SQL,请帮我生成一个优化验证清单。
要求:1. 每一项都能实际执行;2. 包含执行计划、耗时、扫描行数、索引效果;3. 区分必须验证和可选验证;4. 输出表格。

可以得到类似表格:

验证项 类型 观察指标 目的
查看原 SQL 的 EXPLAIN 必须 key、rows、Extra 确认当前执行计划
使用 EXPLAIN ANALYZE 必须 实际耗时、实际扫描行数 对比估算和真实执行情况
去掉关键词条件测试 必须 查询耗时是否明显下降 判断 LIKE/OR 是否为主要瓶颈
去掉用户昵称搜索测试 必须 join 后过滤成本 判断跨表模糊匹配影响
增加 (status, create_time) 索引后测试 必须 rows、是否 filesort、耗时 验证组合索引效果
改订单号为前缀匹配测试 可选 是否使用订单号索引 验证订单号搜索优化空间
拆分订单号和昵称搜索 SQL 可选 不同路径的耗时 验证拆查询是否更稳定
检查慢查询日志 必须 执行频率、平均耗时 判断是否为高频慢 SQL
检查分页页码 可选 深分页耗时 判断是否存在 LIMIT offset 问题

这种清单很适合放到 issue 或技术方案里。
团队沟通时,也比一句“这个 SQL 要优化”清楚得多。


八、一个可能的优化方向

在当前信息下,可以先尝试一个相对基础的优化方向。

1. 增加组合索引

sql

CREATE INDEX idx_order_status_create_timeON t_order(status, create_time DESC);

如果 MySQL 版本对降序索引支持有限,也可以使用:

sql

CREATE INDEX idx_order_status_create_timeON t_order(status, create_time);

然后重新执行:

sql

EXPLAIN SELECT ...

重点观察:

  • key 是否使用了新索引;
  • rows 是否明显下降;
  • Extra 中是否还有 Using filesort
  • 实际查询耗时是否下降。

2. 拆分关键词搜索

原始写法:

sql

AND (    o.order_no LIKE '%202601%'    OR u.nickname LIKE '%张%')

可以根据业务规则拆开。

如果关键词像订单号:

sql

AND o.order_no LIKE '202601%'

如果关键词像昵称:

sql

AND u.nickname LIKE '%张%'

甚至在昵称查询场景下先定位用户,再查订单。

3. 限制后台查询时间范围

后台列表查询如果默认查全量,非常容易慢。
可以在产品层面限制默认时间范围,例如:

  • 默认查最近 7 天;
  • 最多查询 90 天;
  • 超过范围走导出任务。

这类优化不只是技术问题,也和产品交互有关。

4. 避免深分页

如果后台存在这种查询:

sql

LIMIT 100000, 20

性能会很差。

可以考虑改成基于游标的翻页:

sql

WHERE create_time < 上一页最后一条记录的create_timeORDER BY create_time DESCLIMIT 20;

或者结合 id 做稳定排序:

sql

WHERE (create_time, id) < (?, ?)ORDER BY create_time DESC, id DESCLIMIT 20;

九、让 ChatGPT 5.5 辅助写复盘文档

SQL 优化完成后,最好不要只在群里说一句“已优化”。
可以让 ChatGPT 5.5 帮忙整理成复盘文档。

Prompt 示例:

text

请根据下面的慢 SQL 排查过程,整理一份技术复盘。
要求:1. 包含问题背景、影响范围、排查过程、根因分析、优化方案、验证结果、后续建议;2. 不要编造没有提供的数据;3. 对不确定内容标记为待确认;4. 语言适合 CSDN 技术文章或团队内部文档。

复盘结构可以是:

markdown

## 1. 问题背景
订单列表接口在数据量增加后响应变慢,接口平均耗时升高。
## 2. 影响范围
- 后台订单列表查询;- 高峰期查询响应变慢;- 暂未影响订单创建主流程。
## 3. 排查过程
1. 查看接口日志,确认耗时集中在订单查询。2. 获取原 SQL 和执行计划。3. 发现订单表扫描行数较多。4. 分别测试去掉关键词条件、去掉昵称条件后的耗时。5. 验证组合索引效果。6. 对关键词查询进行拆分。
## 4. 优化方案
1. 增加组合索引 `(status, create_time)`。2. 根据关键词类型拆分查询路径。3. 限制默认查询时间范围。4. 后续评估是否引入搜索引擎。
## 5. 验证结果
待补充真实压测数据。
## 6. 后续建议
1. 对高频后台查询建立慢 SQL 监控。2. 新增复杂查询前先评估索引。3. 对关键词搜索类需求单独设计查询方案。

这种复盘文档对团队很有价值。
因为 SQL 优化不是一次性工作,后面类似问题还会出现。把排查过程沉淀下来,下次会快很多。


十、使用 ChatGPT 5.5 分析慢 SQL 时的注意点

虽然 ChatGPT 5.5 可以辅助分析 SQL,但有几个点一定要注意。

1. 不要让模型凭空猜数据分布

SQL 优化高度依赖数据分布。
同一条 SQL,在 10 万数据和 1 亿数据下,优化策略可能完全不同。

最好提供:

  • 表数据量;
  • 字段基数;
  • 条件命中比例;
  • 执行计划;
  • 慢查询日志;
  • 实际耗时。

2. 不要盲目照抄索引建议

模型可能会建议很多索引,但索引不是越多越好。

索引会带来:

  • 写入变慢;
  • 占用磁盘;
  • 增加维护成本;
  • 可能让优化器选择变复杂。

上线前一定要在测试环境验证。

3. 不要只看 EXPLAIN

EXPLAIN 是估算,不能完全代表真实执行情况。
如果 MySQL 版本支持,建议配合:

sql

EXPLAIN ANALYZE

看真实执行时间和真实扫描行数。

4. 不要忽略业务改造

有些慢查询不是单纯靠索引能解决的。
比如任意关键词搜索、深分页、大范围导出,这些更适合从业务设计上调整。

5. 不要把模型输出当最终结论

模型输出应该作为排查参考,而不是上线依据。
最终是否有效,要靠执行计划、压测数据和线上监控确认。


总结

ChatGPT 5.5 用在慢 SQL 排查中,比较合适的位置不是“直接给答案”,而是帮助开发者把信息整理清楚:

  • SQL 当前做了什么;
  • 哪些条件可能影响索引;
  • 执行计划暴露了哪些问题;
  • 下一步该验证什么;
  • 优化方案有哪些取舍;
  • 最终如何形成复盘文档。

对于订单列表、后台查询、关键词搜索、分页接口这类常见慢 SQL 场景,它能明显提高排查效率。

但数据库优化最终还是要回到真实数据上。
执行计划、扫描行数、字段选择性、查询频率、并发压力,这些才是决定优化方案是否有效的关键。

简单说:ChatGPT 5.5 可以帮你少走弯路,但不能替你完成验证。真正可靠的优化,一定是模型辅助分析加上实际数据验证。

更多推荐