同一句SQL我却找不出慢在哪|拆完七段执行流程,答案在SQL之外

简介: 从一次接口超时告警切入,把一条 SQL 在 MySQL 里的完整路径拆成七段(连接器、查询缓存、解析器、预处理器、优化器、执行器、存储引擎),用 optimizer_trace 和 Handler_read 变量判断慢在哪一段,并给出慢查询排查的顺序与三个避坑经验。

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

上周三凌晨,一个订单查询接口的 P99 从 40 毫秒掉到了 3 秒。告警响的时候我正在改另一篇稿子。我把慢日志里那条 SQL 抄出来,翻来覆去看了一个小时。有索引,条件不复杂,没子查询,没排序,我找不出毛病。后来我拉了两个数出来看。一个是执行器向存储引擎要数据的次数,那条 SQL 只返回 20 行,引擎层却被问了上百万次。另一个是优化器的决策记录,它选的路径也不是我预期的那条。

那一刻我才明白,我一直在 SQL 文本里找答案。答案不在文本里,在它被执行的这条路上。

一条 SQL 要过七道关

我刚转行那会儿,以为 SQL 发出去,数据库就直接去磁盘翻数据了。不是这么回事。它得先被认出来,被检查,被改写,被规划,最后才由执行器一行一行去向存储引擎要数。

我把它拆成七段。前六段在 Server 层,最后一段在引擎层。这个分层最有用的一点是,你看到的慢,可能压根还没碰到数据。

阶段 干什么 出问题的症状
连接器 握手、认证、授权 连接数爆满、认证慢
查询缓存 按 SQL 文本查缓存(8.0 已移除) 现在是历史包袱
解析器 词法语法分析,生成语法树 报错指向某个 token
预处理器 查表、列、权限,展开视图 表不存在、无权限
优化器 选访问路径、选 JOIN 顺序 执行计划突变、索引不走
执行器 调引擎接口,逐行取数 取数次数爆炸
存储引擎 索引定位、Buffer Pool、回表、加锁 锁等待、刷脏、IO 打满

前面四段:SQL 还没开始跑

连接器是唯一跟 SQL 内容没关系的一段。TCP 握手,验证账号密码,从权限表读权限缓存起来。这个连接从此独占一个线程,直到断开。

权限缓存这件事值得记一笔。你在会话中途改了权限,有时候不生效,得重新连一次才认。长连接还会攒内存。我现在的习惯是让连接池配好最大存活时间,别让一个连接活到天荒地老。

第二段是查询缓存。它在 MySQL 8.0 被整个删掉了。我刚知道的时候有点意外,毕竟听着挺划算。后来想明白了,它按整张表失效。这张表只要有任意一次写入,表上所有缓存全废。对写多读少的业务来说,维护成本比省下来的还高。而且每次查缓存都要加锁。删得对。这件事也提醒我,缓存的失效粒度比缓存本身更值得琢磨。

第三段解析器干两件事。词法分析把一长串字符切成一个个 token。语法分析再按规则把它们拼成语法树。你写错语法时看到的那个 near 'xxx',就是它卡住的位置。第四段预处理器拿着语法树去数据字典核对,确认表和列真的存在,你真有权限。

这两段快到几乎零成本。但它们说明一件事,SQL 进数据库后的第一步不是执行,是理解。

第五段:优化器,路真正分岔的地方

前四段是确定性的,同一句 SQL 每次走的路一样。到优化器就变了。它要在好几条能走通的路里挑一条。挑什么?全表扫还是走索引,走哪个索引,多表 JOIN 先连哪两张,用哪种连接算法。挑的依据是代价估算,估算靠统计信息和代价常量。

我那个告警的答案就在这儿。我打开 optimizer_trace,看到了它的决策过程。它比了三条访问路径,选了一条跟我预期完全不同的。原因是它算错了这张表要返回多少行。

为什么算错,因为统计信息是随机采样出来的。采样页数有限,数据一倾斜它就看不准。这块内容够单独写一篇,今天先记住一个结论:优化器每次选路都基于估算,不基于事实。它每次都可能改主意。

-- 打开优化器追踪,只对当前会话生效
SET optimizer_trace = 'enabled=on';
SET optimizer_trace_max_mem_size = 1048576;

-- 把要查的 SQL 原样跑一遍
SELECT id, order_no, amount
FROM orders
WHERE user_id = 1024 AND status = 3
ORDER BY created_at DESC
LIMIT 20;

-- 看优化器的完整决策记录
SELECT TRACE FROM information_schema.optimizer_trace\G

第六、七段:逐行的真相

拿到执行计划以后,执行器开始干活。它会再判一次权限。然后按计划里的算子一层层往下走,向存储引擎要数据。

关键在"逐行"两个字。它不是一批一批地拿。它打开接口以后一行一行地取,取够条件才往上交。所以一条只返回 20 行的 SQL,引擎层可能被调了上百万次。大部分行在半路就被丢掉了。

-- 看执行器和引擎之间到底交互了多少次
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM performance_schema.session_status
WHERE VARIABLE_NAME IN (
  'Handler_read_first', 'Handler_read_key',
  'Handler_read_next', 'Handler_read_rnd_next'
);

第七段进 InnoDB。走主键索引直接定位到页。走二级索引就先拿主键再回表,除非是覆盖索引。Buffer Pool 命中就不用读盘,没命中才从磁盘读页。锁也在这一层加,行锁在引擎层,MDL 在 Server 层。

我以前排障是一上来就翻慢日志。现在中间会插一步,先看一眼 Handler_read 这几个变量。交互次数远远超过返回行数,那问题多半在"取了很多又丢掉",往执行计划的方向查。次数正常但还是很慢,那更可能是锁等待或者 IO,得换条路查。

避坑清单

optimizer_trace 有内存上限,超了就截断,结尾看不到。它还是会话级的,换个连接就没了。如果想在事后复现,需要在问题复现时当场开着。

SHOW PROFILE 这两个词网上教程到处都是。但它在较新的版本里已经不是推荐做法了,performance_schema 才是正经路子。具体到你手上的版本还支不支持,动手前先确认,别照着老文章抄。

最后一条是我自己搞错的。我以前看 EXPLAIN 只看 type 列,看到 ref 或者 range 就觉得稳了,从来不看 rows。后来才知道 rows 是估算值,那个数字本身可能就是优化器算偏的结果。现在我习惯把 rows 和 EXPLAIN ANALYZE 出来的实际行数放一起比。EXPLAIN ANALYZE 会真正执行 SQL,生产环境慎用,建议在测试环境或只读副本上操作。两者差得离谱,就先别急着调 SQL,去治统计信息。

写在最后

这次告警教我一件事,定位 SQL 慢不能只盯着 SQL,得知道它此刻走在哪一段。卡在连接,卡在锁,还是卡在选路上,这三类的排查手法完全不一样。一上来就翻慢日志,等于把七个病人塞进一个诊室。

我不是说慢日志没用。它是入口,不是答案。我现在的顺序是先看慢日志拿到 SQL,再用 EXPLAIN 看计划,用 optimizer_trace 看优化器怎么想的,用 Handler 变量看执行器怎么要数的,最后才去猜引擎层。

一条 SQL 跑得慢,从来不是 SQL 自己的错。它只是老老实实走完了这七段路,把每一段的耗时加总还给你。你要做的,是找出是哪一段。

你上一次排查慢 SQL,卡在哪一段?评论区聊聊。

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

相关文章
|
11天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
11天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
18天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)
|
10天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1184 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
12天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1967 15
|
12天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
17天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1680 4
|
18天前
|
缓存 数据可视化 开发工具
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
DeepSeek Harness 的更新分两层:本体更新(npx 自动最新、npm update -g、源码 git pull)与插件更新(插件市场点更新、命令行覆盖安装)。本文按「准备 → 更新本体 → 更新插件 → 更新后检查」四步走,覆盖新手常见疑问。
1996 1
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
|
13天前
|
SQL 人工智能 前端开发
QoderWake 1.0 正式发布:从桌面里的 Agent,到工作现场的数字员工
QoderWake v1.0正式发布:企业级数字员工团队平台。支持“一句话建岗”,预置10类特训岗位;Waker常驻钉钉/飞书群,@即响应、自动协作、跨任务记忆;具备定时/事件/API多触发方式与统一任务看板;已沉淀27.6万条记忆、12.3万项技能,助力组织实现人机协同增效。
854 3
|
11天前
|
缓存 测试技术 API
DeepSeek V4.1 Flash 内测接入:改个模型名即可调用(附代码)
DeepSeek V4.1 Flash 内测不用申请,base_url 不变、改个模型名就能调,9/10 到期。本文讲清接入、计费限流与多模态注意点。
862 0
DeepSeek V4.1 Flash 内测接入:改个模型名即可调用(附代码)