在数据库性能调优领域,MySQL DBA 和开发者长期依赖 EXPLAIN 语句来理解查询执行计划。然而,传统的 EXPLAIN 输出仅提供优化器估算的成本和行数,缺乏实际执行时的关键指标,如每步操作的真实耗时、循环次数和行处理量。自 MySQL 8.0.18 引入 EXPLAIN ANALYZE 后,我们终于能获取查询执行的实际统计数据,但面对多层嵌套、文本格式的输出,快速定位性能瓶颈依然挑战重重。
本文将深入介绍一款专为 MySQL 设计的开源可视化工具 ——myflames,它巧妙地将 EXPLAIN ANALYZE 的输出转化为交互式火焰图(Flame Graph),让查询执行计划的时间分布一目了然。该工具由社区开发者 Vinicius Malvestio Grippa 维护,灵感源自 Brendan Gregg 的经典 FlameGraph 项目以及 Tanel Pöder 在 Oracle 场景下提出的 SQL 计划火焰图概念。
工具原理与技术栈
myflames 的核心工作流程分为三步:数据提取、堆栈折叠与可视化渲染。
- 数据提取:工具要求 MySQL 8.4+ 并启用
explain_json_format_version = 2配置,以获取结构化的EXPLAIN ANALYZE FORMAT=JSON输出。该 JSON 包含了查询执行的树形结构,每个节点记录了operation(操作类型)、actual_rows(实际行数)、actual_loops(循环次数)、actual_last_row_ms(完成耗时)等关键字段。 - 堆栈折叠:内置的 Perl 脚本
stackcollapse-mysql-explain-json.pl解析 JSON,将执行计划转换为 “折叠堆栈” 格式。每一行代表一个从根到叶子的调用路径,用分号分隔各级操作,末尾附上该路径的总耗时(微秒或毫秒)。这种格式是 Brendan Gregg FlameGraph 工具的通用输入。 - 可视化渲染:将折叠堆栈输送给
flamegraph.pl脚本,生成 SVG 格式的交互式火焰图。SVG 内嵌 JavaScript,支持缩放、搜索和丰富的悬停提示。
工具提供了两种主要视图:火焰图(默认)和条形图。火焰图以层次化方式展示执行流,宽度代表包含子操作的总时间,便于理解整体流程;条形图则按 “自时间”(操作自身耗时,不含子操作)降序排列,直击最耗时的单个操作。
安装与快速上手
环境准备
- MySQL 8.4+,并在
my.cnf中设置explain_json_format_version = 2。 - Perl 5.x(多数 Unix/Linux/macOS 系统已预装)。
- 克隆 myflames 仓库:
git clone https://github.com/vgrippa/myflames.git cd myflames chmod +x *.pl
三步生成你的第一张火焰图
-
获取查询的 EXPLAIN ANALYZE 输出:
-- 在 MySQL 客户端中执行 EXPLAIN ANALYZE FORMAT=JSON SELECT * FROM your_table WHERE condition;将输出的 JSON 保存为文件,如
explain.json。 -
生成火焰图:
./mysql-explain-flamegraph.pl explain.json > query_plan.svg -
查看与交互: 用浏览器打开
query_plan.svg。你可以悬停查看操作详情、点击放大、使用/搜索特定操作(如 “Index lookup”)。
参数详解与定制化输出
myflames 提供了丰富的命令行参数,适应不同分析场景。
火焰图生成器 (mysql-explain-flamegraph.pl)
--width与--height:调整 SVG 的尺寸,默认宽度 1800 像素,每帧高度 32 像素。对于复杂查询,可增加宽度以容纳更多细节。--colors:配色方案。内置hot(热力图,默认)、mem(内存风格)、io(I/O 风格)、red、green、blue等。绿色系 (green) 在长时间审视时更舒适。--title:自定义图表标题,便于后续区分和报告。--inverted:生成冰柱图(反转火焰图),视觉上更符合 “自上而下” 的阅读习惯。--no-enhance:禁用增强型工具提示,仅显示基础信息。
条形图生成器 (mysql-explain-bargraph.pl)
- 专注于 “自时间” 排序,参数较少,主要使用
--width和--title。
高级用法示例
# 生成一个绿色、标题明确、宽度加大的冰柱图
./mysql-explain-flamegraph.pl --colors green --title "订单报表查询性能分析" --width 2400 --inverted explain.json > order_report.svg
# 直接通过管道从 MySQL 获取数据并生成图表
mysql -u user -p -N -e "EXPLAIN ANALYZE FORMAT=JSON SELECT ..." database | \
./mysql-explain-flamegraph.pl > live_query.svg
如何解读火焰图:定位优化点的实战指南
一张生成的火焰图不仅仅是 “好看的图片”,更是性能诊断的路线图。阅读时遵循以下步骤:
- 识别最宽的 “砖块”:火焰图中最宽的横向条带代表了最耗时的执行路径。将鼠标悬停其上,工具提示会显示详细数据,如
rows=5000、loops=10,意味着该操作处理了海量数据或被执行了多次。 - 理解层次结构:从底部(根操作,通常是
SELECT)到顶部(叶子操作,如具体的索引扫描或过滤),每一层代表一个调用关系。如果某一层突然变宽,说明时间主要消耗在该层及其子操作上。 - 关注关键指标:
rows与loops:如果rows远大于预估或loops数值巨大,可能意味着连接条件低效或索引缺失。actual_last_row_ms:操作的绝对耗时。结合loops可计算总消耗(耗时 * loops)。index_name:如果工具提示显示index_name: NULL或使用了非最优索引,这就是明确的优化信号。
- 利用交互功能:
- 搜索:按
/键,输入SCAN可快速定位全表扫描操作。 - 缩放:点击感兴趣的条带可放大查看细节,点击顶部的 “Reset Zoom” 复位。
- 对比:对优化前后的查询分别生成火焰图,并排比较宽度变化,直观验证优化效果。
- 搜索:按
高级场景与集成
监控与自动化
将 myflames 集成到 CI/CD 管道或定期监控任务中,可以自动分析关键查询的性能趋势。编写一个 shell 脚本,定期执行预设查询、生成火焰图并归档,配合简单的图像差异检测,可在性能回归发生时及时告警。
与现有生态集成
myflames 生成的 SVG 可轻松嵌入到团队 Wiki、性能报告甚至 Grafana 仪表板(通过 SVG 面板插件)中,实现性能数据的可视化共享。
局限性及替代方案
尽管 myflames 功能强大,但需注意其局限:
- 版本依赖:必须使用 MySQL 8.4+ 并正确配置 JSON 格式版本。对于旧版本,可参考前述博客文章中的方法,手动解析
EXPLAIN ANALYZE的文本输出,但过程繁琐。 - 仅限单查询分析:工具专注于单个查询的执行计划剖析,对于系统级、并发场景下的性能问题,仍需结合
PERFORMANCE_SCHEMA、sys模式以及perf+ 系统级火焰图进行综合诊断。 - 子查询与复杂计划:对于包含大量子查询或临时表操作的超复杂计划,火焰图可能变得非常宽,需要结合缩放功能仔细分析。
当 myflames 不适用时,可考虑以下替代可视化方案:
- Percona Monitoring and Management (PMM):提供 Query Analytics 仪表板,以表格和图表形式展示查询性能指标。
- 手动脚本 + 其他可视化库:利用 Python 的
pandas+matplotlib或plotly库,自定义解析 JSON 并绘制时间分布堆叠图。
结语
myflames 工具将经典的火焰图可视化技术成功应用于 MySQL 查询执行计划领域,填补了从文本解释到直观图形之间的鸿沟。通过将 EXPLAIN ANALYZE 的深层数据转化为可交互、可搜索的视觉表示,DBA 和开发者能够以前所未有的速度定位查询瓶颈,验证优化假设,并建立更高效的数据库访问模式。
正如工具作者在 FOSDEM 2022 演讲中所强调的,可视化不仅是为了 “更好看”,更是为了 “更易懂”。在数据驱动的性能优化旅程中,像 myflames 这样的工具无疑是一盏明亮的探照灯,照亮了曾经晦涩难懂的执行计划细节。
资料来源
- myflames GitHub 仓库:https://github.com/vgrippa/myflames - 工具源码、示例及详细文档。
- 技术博客《Visualizing MySQL Plan Execution Time With Flame Graphs》:http://mysqlentomologist.blogspot.com/2022/01/visualizing-mysql-plan-execution-time.html - 提供了手动实现火焰图的底层原理与技巧。