当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL optimizer_trace 观察成本估算分支

MySQL optimizer_trace 观察成本估算分支

来源:17golang原创 2026-10-28 08:01:19 0浏览 收藏

排查 MySQL 查询为什么选择了某条访问路径时,EXPLAIN 能告诉你结果计划,却不一定能说明优化器比较过哪些候选、估算了多少行、给每条路径算出了什么成本。optimizer_trace 可以把这段优化过程写入 JSON,适合回答“为什么这个分支被选中”“为什么范围访问没有被采用”这类问题。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/optimizer-tracing.html

本文只聚焦成本估算分支:在同一会话中打开跟踪,执行一条目标 SQL,再从 INFORMATION_SCHEMA.OPTIMIZER_TRACE 里顺着 rows_estimation、range_analysis 和 considered_execution_plans 阅读。示例中的数值是为了说明字段关系,不代表你的业务库会得到相同结果。

为什么 EXPLAIN 还不够看懂成本选择

EXPLAIN 更像最终计划的摘要:你可以看到访问类型、候选索引以及估算行数,但当多个路径都可用时,摘要通常不会把“候选 A 为什么输给候选 B”的过程完整展开。优化器跟踪则保留了更多中间决策,例如表扫描和索引访问的估算行数、成本、是否被选中,以及计划累计成本。

因此,optimizer_trace 适合短时间定位一个具体问题,而不是长期打开当作普通监控。官方文档给出的基本步骤也是开启跟踪、执行待分析语句、读取 OPTIMIZER_TRACE,完成后关闭跟踪;跟踪只对当前会话可见。

optimizer_trace 从 SQL 和统计信息连接到成本估算分支与 JSON trace 的静态结构图
图1:optimizer_trace 成本估算分支的静态结构图,不是截图,也不是本机运行证据。

先在同一会话打开并读取跟踪

最容易犯的错误是:在连接 A 打开跟踪,却在连接 B 执行查询或读取结果。优化器跟踪按会话保存,换连接后看不到刚才的 trace。下面的 SQL 要在同一个 MySQL 客户端连接中依次执行。

-- 只在当前会话打开优化器跟踪,并让 JSON 更容易人工阅读
SET optimizer_trace = 'enabled=on,one_line=off';

-- 执行需要分析的查询;这里的表名和条件请替换为你的目标 SQL
SELECT o.order_id, o.customer_id
FROM orders AS o
WHERE o.customer_id = 10086
ORDER BY o.order_id DESC
LIMIT 20;

-- 读取当前会话最近保留的 trace,\G 只负责纵向展示结果
SELECT QUERY, TRACE, MISSING_BYTES_BEYOND_MAX_MEM_SIZE,
       INSUFFICIENT_PRIVILEGES
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE\G

-- 分析完成后关闭跟踪,避免继续记录后续语句
SET optimizer_trace = 'enabled=off';

one_line=off 只影响 JSON 的空白格式,便于人工阅读;如果结果要交给 JSON 解析器,空白并不影响解析。重点是执行 SQL 和读取表必须保持在同一连接中。读取结果时优先看 QUERY,先确认这条 trace 对应的确实是目标语句。

从 OPTIMIZER_TRACE 找到成本估算分支

TRACE 是 JSON 文本,字段会随着语句类型、表数量和优化过程变化,不建议只按固定层级下标读取。人工排查时可以先搜索这些语义节点:

  • rows_estimation 或 records_estimation:查看扫描、范围分析等行数与成本估算。
  • range_analysis:查看表扫描、潜在范围索引和范围访问相关判断。
  • considered_execution_plans:查看优化器比较过的执行计划。
  • best_access_path 与 considered_access_paths:查看某张表的候选访问路径。

官方示例在记录估算中展示了 table_scan、records 和 cost,在候选计划中展示了 access_type、index、records、cost 和 chosen。这就是标题所说的“成本估算分支”:不是只看最终索引名,而是沿着估算节点看每个候选如何进入比较。

-- 只抽取原始 JSON 文本;不要假设每种 SQL 都有相同字段
SELECT TRACE
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE
WHERE QUERY LIKE 'SELECT o.order_id%';

用 cost、records 和 chosen 对上决策

阅读一段候选访问路径时,可以按“候选是什么—预计读多少—代价是多少—是否采用”的顺序看:

字段阅读重点不要误读成
records / rows该候选预计产生或读取的行数实际执行后一定返回的行数
cost优化器用于比较候选的估算代价毫秒数或线上真实耗时
chosen当前比较节点是否选用这条路径所有后续执行阶段都永远使用它
cost_for_plan当前计划组合的累计估算代价一次请求的最终账单

例如,同一个 best_access_path 里可能同时出现 scan 和 ref。先比较它们的估算行数和成本,再看 chosen 是否为 true。如果某条路径的成本更高但仍被选中,不要立刻断言跟踪错误,还要继续确认它是否属于不同的计划前缀、连接顺序或后续代价累计。

同时要把“估算原因”和“运行结果”分开:optimizer_trace 解释的是优化器在生成计划时的判断;它不是执行耗时剖析,也不能替代真实运行指标。

considered_execution_plans 中 scan 与 ref 候选通过 cost 和 chosen 连接到最终计划的静态结构图
图2:候选访问路径与 chosen、cost_for_plan 的关系示意图,不是截图,也不是运行结果。

trace 太大时先控制分支和内存

复杂连接、范围分析或重复执行的子查询会让 trace 很快变大。MySQL 8.4 提供了几组会话级控制项:

-- 提高本次分析允许保存的 trace 总内存;数值按语句复杂度调整
SET optimizer_trace_max_mem_size = 1000000;

-- 只查看保留结果中的一部分;limit 和 offset 用于控制展示窗口
SET optimizer_trace_limit = 1;
SET optimizer_trace_offset = 0;

-- 对容易重复产生噪声的优化器分支关闭跟踪
SET optimizer_trace_features =
    'greedy_search=off,range_optimizer=on,dynamic_range=on,repeated_subselect=off';

optimizer_trace_features 的四个开关分别影响贪心搜索、范围优化器、动态范围优化和重复子查询跟踪。关闭某个开关的含义是“不记录该类分支”,不是关闭查询优化本身。调试成本估算时,不要为了让 JSON 变短而随意关闭你正在研究的分支;先关闭与当前问题无关的重复噪声。

看到截断或空 trace 时怎么判断

先检查 MISSING_BYTES_BEYOND_MAX_MEM_SIZE。如果它大于 0,说明 trace 达到 optimizer_trace_max_mem_size 后没有继续扩展,当前结果是不完整的,应提高会话级内存上限后重新执行目标语句,而不是把缺失部分当成“优化器没有走这条分支”。

再看 INSUFFICIENT_PRIVILEGES。官方文档指出,涉及以 SQL SECURITY DEFINER 定义的视图或存储程序时,当前用户可能无权看到完整 trace;这时 trace 可能为空,并且该列值为 1。它是权限边界,不等同于目标 SQL 没有优化过程。

还要确认语句属于可跟踪范围,并且没有跨连接读取。最稳妥的排查顺序是:确认 QUERY、确认当前连接、确认内存缺失字节、确认权限列,最后再调整跟踪开关。

一次分析结束后恢复会话状态

optimizer trace 是定位工具,文章示例完成后应关闭。若你在共享客户端里继续执行其他 SQL,保留的 trace 还会影响后续阅读,因此建议把“打开—执行—读取—关闭”放在一个短流程内。

-- 恢复为关闭状态,避免把后续无关语句继续写入 trace
SET optimizer_trace = 'enabled=off';

-- 需要重新分析时,从清晰的会话状态开始检查当前参数
SELECT @@optimizer_trace,
       @@optimizer_trace_features,
       @@optimizer_trace_max_mem_size,
       @@optimizer_trace_limit,
       @@optimizer_trace_offset;

如果本次目的是解释一个索引或连接顺序选择,最终应把 trace 中的成本判断与 EXPLAIN 的最终计划放在一起阅读:前者说明候选和估算过程,后者说明计划摘要。两者回答的问题不同,不能用其中一个替代另一个。

常见问题

optimizer_trace 会记录其他连接的 SQL 吗?

不会。官方说明是只能跟踪当前会话中执行的语句,不能从另一个会话查看。

cost 是真实耗时吗?

不是。它是优化器用于比较候选计划的估算值,不能直接当作毫秒、CPU 时间或磁盘耗时。

为什么 TRACE 里找不到 range_analysis?

字段是否出现取决于语句结构和优化阶段。不要把某个示例的 JSON 路径当成固定 schema,先确认目标 SQL 是否确实产生范围分析,再沿着 rows_estimation 或 considered_execution_plans 查找实际存在的节点。

增大 optimizer_trace_max_mem_size 就一定能解决空结果吗?

不一定。它只针对因跟踪内存上限造成的不完整 trace;如果 INSUFFICIENT_PRIVILEGES=1,应先处理视图或存储程序的权限边界;如果是跨会话读取,也应回到执行目标 SQL 的连接。

总结

观察 MySQL 成本估算分支的关键,不是盯着一行最终索引,而是让 optimizer_trace 暂时记录优化过程,再从 OPTIMIZER_TRACE 里把候选路径、估算行数、成本和 chosen 对应起来。记住三点:同一会话执行和读取、把 cost 当估算值而不是耗时、遇到截断或空 trace 先检查内存和权限。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL 生成列配合索引的 JSON 字段检索MySQL 生成列配合索引的 JSON 字段检索
上一篇
MySQL 生成列配合索引的 JSON 字段检索
MySQL 在线 DDL 的锁等待控制方法
下一篇
MySQL 在线 DDL 的锁等待控制方法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    748次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    745次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    831次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    796次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    630次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码