跳到正文
阿里雲開發者社區 AI·· 3 小時前AI 評分59

同一條慢 SQL,AI 建議加索引,真正原因是鎖等待

同一条慢SQL,AI让我加索引,真凶是锁等待

AI 導讀

作者用四條 MySQL 8.0 慢 SQL 測試 AI 根因判斷,結果是兩條判對、一條偏差、一條錯誤。補上執行計劃、鎖等待等現場資料後,AI 將一宗加索引的判斷修正為長事務造成的行鎖等待。文章並提供提示詞模板及驗證清單,建議把 AI 給出的根因視為假設,逐項上機核實。

正文

简介: 把四条真实慢 SQL 连同表结构、执行计划、锁等待现场分两轮喂给 AI,按“指向真实瓶颈、给出可验证假设、分清计划与执行”三项标准判定。四条里两对一偏一错,拆清它擅长已知模式、盲区在现场证据,并给出提示词模板与验证清单,最后讨论 AI 数据库把现场证据接进模型后的边界。

大家好,我是数据库小学妹👋 我踩过的坑,你别再踩。

前阵子我攒了四条挺典型的慢 SQL。每条都带着表结构、执行计划和慢日志的时间点。我把它们一起丢给 AI,让它直接给根因。连着测了几轮,结果有点意外。

它判对的地方很干脆,一句话点到要害。判错的地方也很统一,几乎都往「缺索引」上靠。有一条它斩钉截铁让我加索引。我真去加了,查询没快多少,写入还慢了一截。真正的堵点,是一条四十秒没提交的事务。所以这篇不讲 AI 能不能用。只讲一件事:它给的根因,什么时候能信。

先定标准,什么算判对了

不先定标准,测完只会剩一句「感觉还行」。我给每条结论定了三关。第一,指向真实瓶颈。说「加索引」不算。得说清走错了哪条路径,扫了多少行,慢在哪一段。第二,给出可验证的假设。能落成一条 SQL 或一个计数器,上机跑一遍就能证实或证伪。第三,分清计划问题和执行问题。是优化器选错了路,还是执行时在等锁、等 IO、等网络。三关全过算对,过两关算偏,只过一关算错。这样评,比「看着挺专业」靠谱。

怎么测的,两轮喂料

为了公平,四个案例用同一个实例,MySQL 8.0,同一批表。第一轮只给 AI 一条 SQL 加建表语句,模拟大多数人平时的用法。第二轮补齐材料:EXPLAIN ANALYZE、表行数、慢日志的时间点、当时的 processlist 和锁等待。

两轮的结论我都记下来,再逐条上机验证。这么做是想看清一件事。它判错,是推理不行,还是材料不够。(下面的表名、行数和耗时,是我为了讲清楚搭的示意场景。拿你自己的慢 SQL 复测,结论可能不同。)

案例一:缺索引,它一次就判对了

先看一条最常见的。用户查自己最近的订单,表里一百二十万行,user_id 上有单列索引。SQL 长这样:

SELECT id, order_no, amount
FROM t_order
WHERE user_id = 88482 AND status = 2
ORDER BY create_time DESC
LIMIT 20;

第一轮 AI 说缺联合索引,建议按 (user_id, status, create_time) 建。等值列在前,排序列在后,排序列放在等值列之后,列序是对的。我按它的建议加上,再跑 EXPLAIN ANALYZE。扫描行数从一百二十万降到三百多。耗时从一千八百毫秒降到十二毫秒。

这一条三关全过。它的熟悉来自模式。WHERE 有等值条件,ORDER BY 有排序列。字段上又没索引,这就是标准题型。

案例二:它让我加索引,真凶是锁等待

第二条是库存扣减。语句不长,条件也简单,可线上就是慢。

UPDATE t_stock
SET qty = qty - 1, updated_at = NOW()
WHERE sku_id = 10023 AND qty >= 1;

这条走主键,EXPLAIN 就一行,rows 估算是 1。理论上不该慢,可线上 P99 卡到了两秒。我第一反应是机器卡了,差点去翻服务器监控。第一轮 AI 看了 SQL 和表结构,说语句没问题。它顺手建议给 updated_at 加索引,理由是以后按时间查询方便。

我先没动索引,去库里看现场。sys.innodb_lock_waits 一查,有人在等同一行:

SELECT waiting_pid, waiting_query, blocking_pid,
       blocking_query, wait_age, sql_kill_blocking_connection
FROM sys.innodb_lock_waits;

blocking 那条是一个开了四十多秒没提交的事务。它的 trx_query 是空的,说明做完事就没再发语句,锁却没放。再确认一遍:

SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started ASC;

trx_state 是 RUNNING,trx_query 为空,开始时间很早。这就是典型的「事务开着忘了提交」。AI 为什么会看走眼,其实不难理解。执行计划只画路,不画排队。它手里没有锁等待,只能往语句本身猜。第二轮我把锁等待视图和事务列表补给它。它立刻改口,说根因是行锁等待。同一个模型,同一道题,材料一换,结论就换了。

案例三:索引它看走眼了,慢的不是索引

第三条是报表常写的统计。后台每天要查一次上月的数据,最近开始超时。

SELECT COUNT(*) FROM t_order
WHERE status = 3 AND create_time >= '2026-09-01';

表上早就有 (status, create_time)。EXPLAIN 显示 type=range,key 用上了,Extra 里是 Using index。看着完美,实测还要两秒多。第一轮 AI 说索引没走对,建议重建索引,或者加 force index 强制它走。

实际上索引走对了,慢在要数的行太多。这个月区间里有三百多万行,覆盖扫描也得一条条数过去。改法不在索引上,是换统计方式。按天预聚合一张指标表,查的时候直接取一行。业务能接受近似值,也可以改成采样。

AI 的判断错在默认「慢就等于缺索引」。可有些查询的代价跟匹配行数成正比。索引只能减少读页,减不了要数多少行。这一条它过了第一关,没过后两关,算偏。

案例四:函数包列,它闭着眼也能看出来

第四条是老朋友。日期过滤,隔一阵就有人踩一次。

SELECT id, user_id FROM t_order
WHERE DATE(create_time) = '2026-10-01';

第一轮它就指出,函数包在列上,索引用不上。改写也给得干净:

SELECT id, user_id FROM t_order
WHERE create_time >= '2026-10-01'
  AND create_time <  '2026-10-02';

上机一验,type 从 ALL 变成 range,耗时从一秒二降到三十毫秒。这类教科书式的失效模式,它答得又快又准。它的强项在模式识别,现场推理是另一回事。

四条摆一起,结论很直接

案例 AI 第一轮结论 实际根因 判定
用户最近订单 加 (user_id, status, create_time) 缺联合索引 对
库存扣减 语句没问题,建议加 updated_at 索引 行锁等待,长事务未提交 错
订单统计 索引没走对,force index 索引已在用,代价在匹配行数 偏
日期过滤 函数包列,改范围查询 同一结论 对

四条里两对一偏一错。这个结果不算差,但说明了一件事。它擅长「见过的问题」,不擅长「正在发生的问题」。

它强在哪,弱在哪

强在三处。一是模式识别快。函数包列、隐式转换、前导模糊、OR 条件,它张口就能点出来。二是能把执行计划讲清楚。key、type、rows、Extra 各是什么意思,它比我打字快。三是改写方案给得多。一条 SQL 能列五六种写法,拿来当候选池很省事。

弱也在三处。第一,它没有现场。锁等待、MDL、IO 打满、buffer pool 命中率、主从延迟,它一个都看不到。第二,它默认把「慢」归到索引上。这是训练语料留下的先验:慢查询的答案八成是加索引。它就顺着这个概率走。第三,它看不到数据分布。同样的 SQL,杭州占八成还是两成,优化器的选择完全不同。它只能猜。

AI 数据库在补的,正是现场这一块

这也是今年厂商都在讲 AI 数据库的原因。10 月 30 日,电科金仓在北京办「Hello, AI数据库」2026 产品发布会。下午还有开发者大会。开发者大会设了内核能力与智能运维专场。它讲的是智能性能调优、性能自治和 KEMCC 运维智能体。方向不难看懂。智能性能调优和性能自治,前提都是先看见现场。把执行计划、等待事件、负载曲线这些证据接进模型。别让它隔着一条 SQL 猜。第二轮我是手动把锁等待贴给它的。AI 数据库想做的,是把这一步自动化。

这正好补上我前面说的盲区。模型看不到锁等待,也看不到数据分布。如果证据由数据库自己采集、自己关联,AI 的起点就不一样。它不再从一段 SQL 文本开始。它能看到谁在等、等了多久、扫了多少行。判断的落点,会从「猜」往「验」挪一步。回头看我那四条,第二条和第三条,缺的都是现场。锁等待、匹配行数,数据库本来就知道。这些信息不用猜,取出来就行。

但我不觉得这能替掉人。发布会给的是方向,具体能力会落到版本和场景里。数据库把证据摆到模型面前,模型给假设,人做最后确认。这个分工不会变。工具越近,越要分清哪一步是它做的,哪一步是你签的字。

怎么用,才不白测

测完我把用法固定成三步。第一步,材料给全。只给 SQL,等于让医生隔空看病。建表语句、现有索引、表行数、EXPLAIN ANALYZE、慢日志时间点,一样都别省。有条件,把当时的锁等待和 processlist 一起贴上。

第二步,要假设,别要结论。直接问根因,它给的是判决。让它给假设,才有验证的空间。我现在的提示词这么写:

你是 MySQL 8.0 的性能工程师。
只做根因假设,不下结论。
输入:SQL、SHOW CREATE TABLE、现有索引、
EXPLAIN ANALYZE、表行数、慢日志时间点。
输出三项:
1. 最可能的三个根因,按可能性排序;
2. 每个根因对应的验证 SQL 或计数器;
3. 每条假设怎样才算被证伪。

第三步,上机验证。它给的假设,逐条拿计数器核对。对不上就划掉,别再顺着它往下想。验证清单我放在下面,照着查就行。

验证清单

怀疑 拿什么验证
优化器选错路 EXPLAIN ANALYZE,真实 rows 对比估算
行锁等待 sys.innodb_lock_waits 或 data_lock_waits
元数据锁 sys.schema_table_lock_waits
索引没生效 key、key_len、type、Extra 一起看
代价在行数 Handler_read_next 与 rows_examined
数据倾斜 ANALYZE TABLE 后重看 rows 与 filtered

它给的是假设,不是结论

AI 的价值,不是替你定案,是替你排除。四条路它能一口气列出来。你去掉两条,剩下两条再验,比一个人空想快得多。

但定案要证据。锁等待是一条查询、一个事务、一个时间点。这些只存在于你的实例里。模型再大,也得有人把现场递到它面前。

避坑清单

别只扔一条 SQL 就让它给根因。材料不全,它只能往最常见的答案靠。结论看着合理,落地就偏。

要它给可验证的假设,而不是「加个索引试试」。假设要能证实,也要能被推翻。只说「试试看」的建议,验不了,也帮不上忙。

最后一条是我自己踩的。那次我信了 AI 的加索引建议,DDL 上完,查询没快,写入还慢了。绕了一大圈才发现,锁在那个没人管的长事务手里。从那以后,我先看等待事件,再看执行计划,最后才聊索引。

写在最后

AI 把「想到」这件事变便宜了。加索引、改写法、换执行路径,它一口气能列七八条。可它也让「确认」变得更贵。候选一多,验证的责任全落回你身上。慢查询的根因,很少整整齐齐写在 SQL 里。它藏在那一刻的锁里,和那一刻的数据分布里。还有那个四十秒没提交的事务。这些证据只在你的实例里。AI 数据库能把它们递到模型面前,但递过去之后,还得有人核对。

它像一位读过很多病例的医生,见识是真的。但病人没进门,它开不出准的药。所以别把 AI 当判官,把它当会诊。它负责把问题铺开,你负责把事实收拢。能问对一个好问题,比得到一个好答案更难。答案是它猜的,事实是你查的。中间那段路,只能自己走。

10 月 30 日,金仓的「Hello, AI数据库」发布会就要开了。我还挺期待。想看看数据库自己把现场证据递到模型面前,能做到哪一步。等发布会结束,我拿真实的慢 SQL 再试一轮。

你们会让 AI 分析慢 SQL 吗?它给过最离谱的结论是什么?评论区聊聊。

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

來源:阿里雲開發者社區 AI · developer.aliyun.com