当前位置:首页 > 文章列表 > 数据库 > MySQL > EXPLAIN FORMAT=JSON 怎样读取窗口节点

EXPLAIN FORMAT=JSON 怎样读取窗口节点

来源:17golang原创 2026-10-25 10:58:41 0浏览 收藏

排查 MySQL 窗口函数时,传统 EXPLAIN 表格往往只能让你看到表访问路径,却看不清窗口计算本身。直接使用 EXPLAIN FORMAT=JSON,重点沿着 query_block.windowing.windows[] 读取,就能看到窗口函数、排序键和临时表信息。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/window-function-optimization.html

要点速览
  • windowing 位于对应的 query_block 下,windows 数组里的每个对象描述一个窗口处理组。
  • functions 说明计算了哪些窗口函数,using_filesort 和 filesort_key 说明是否需要按窗口定义排序。
  • using_temporary_table 只能说明该窗口步骤使用了临时表,不能单独证明查询一定慢。

先让 EXPLAIN 输出窗口节点

先准备一个按部门分区、按薪资排序的查询。这里故意放入两个窗口函数,便于观察 windows 数组如何描述窗口计算:

-- 用一个稳定的员工编号作为并列薪资时的补充排序键。
EXPLAIN FORMAT=JSON
SELECT department_id, employee_id, salary,
       ROW_NUMBER() OVER (
           PARTITION BY department_id
           ORDER BY salary DESC, employee_id
       ) AS department_rank,
       SUM(salary) OVER (
           PARTITION BY department_id
       ) AS department_total
FROM employee_salary
WHERE employment_status = 'active';

结果最外层通常是 query_block。窗口函数对应的执行信息在它的 windowing 节点中,继续向下看 windows 数组,而不是只盯着最外层的 table。

EXPLAIN FORMAT=JSON 从 query_block 到 windowing windows 数组的静态结构说明图
图1:窗口节点结构说明图,展示 SQL 窗口定义与 JSON 计划字段的对应关系,不是运行截图。

按 windows 数组读取一个窗口对象

官方示例中的窗口对象会出现 name、functions、using_filesort、filesort_key 和 using_temporary_table 等字段。可以按下面的顺序读:

字段先回答的问题阅读重点
name它对应哪个命名窗口?没有使用 WINDOW 命名时可能为空字符串。
functions这一组计算了什么?与 ROW_NUMBER、SUM 等窗口函数对照。
using_filesort是否需要排序?为分区和窗口 ORDER BY 准备顺序。
filesort_key按什么排序?和 PARTITION BY、窗口内 ORDER BY 的列或表达式核对。
using_temporary_table是否用了临时表?结合数据量、窗口帧和整体计划判断影响。

不要把数组下标直接当成“第几个 SELECT 输出列”。一个窗口对象描述的是一组窗口处理信息,functions 才是与计算内容直接对应的字段;后面的 table 或 nested_loop 仍要单独阅读。

{
  "windowing": {
    "windows": [
      {
        "name": "",
        "using_temporary_table": true,
        "using_filesort": true,
        "filesort_key": ["`department_id`", "`salary` DESC"],
        "functions": ["row_number"]
      }
    ]
  }
}

上面的 JSON 只用于说明字段形状,不应把示例中的布尔值当成每个查询都会得到的固定结果。实际字段以当前语句和版本输出为准。

结合临时表和窗口顺序判断代价

using_filesort: true 表示窗口步骤需要排序,它不是“必然慢”的结论;要继续看排序键、输入行数和其他访问路径。using_temporary_table: true 表示窗口处理中使用了临时表,涉及需要保存或重新访问行的窗口帧时更值得关注。

如果查询包含多个窗口,不要只数数组元素。MySQL 会关注不同窗口的分区和排序要求;排序要求相同的窗口可以连续处理,后续窗口可能复用已有顺序。改写 SQL 时,可以把重复的窗口定义写成命名窗口,减少表达式分散带来的阅读成本:

-- 给相同的分区和排序定义命名,避免多个 OVER() 各写一套表达式。
EXPLAIN FORMAT=JSON
SELECT department_id, employee_id, salary,
       ROW_NUMBER() OVER department_window AS row_no,
       RANK() OVER department_window AS salary_rank
FROM employee_salary
WHERE employment_status = 'active'
WINDOW department_window AS (
    PARTITION BY department_id
    ORDER BY salary DESC, employee_id
);
窗口排序、临时表和多个窗口函数之间关系的静态说明图
图2:窗口代价阅读说明图,展示排序键、临时表与函数组之间的静态关系,不是运行截图。

用固定路径做排查记录

实际对比改写前后的计划时,我会把记录拆成四层:先确认 query_block,再确认是否有 windowing,接着逐个读取 windows[],最后回到同一节点下的 table、nested_loop 和成本信息。这样能避免把“访问表很快”和“窗口排序很轻”混成一个结论。

-- 用同一条语句保存改写前后的 JSON 计划,便于逐字段比较。
EXPLAIN FORMAT=JSON
SELECT department_id, employee_id,
       ROW_NUMBER() OVER (
           PARTITION BY department_id
           ORDER BY salary DESC, employee_id
       ) AS row_no
FROM employee_salary
WHERE employment_status = 'active';

如果没有看到 windowing,先确认当前语句真的含有窗口函数,并检查是否查看了正确的 query_block。如果有 windowing 但没有排序字段,不要自行补猜;只记录当前版本实际返回的字段。MySQL 文档明确指出,窗口执行信息过于丰富,传统输出无法完整展示,因此读取窗口节点应以 JSON 计划为主。

常见问题

为什么传统 EXPLAIN 看不到窗口函数的详细信息?

窗口处理信息较丰富,传统表格格式无法完整承载;应改用 EXPLAIN FORMAT=JSON 查看 windowing。

看到 using_filesort 就一定要改 SQL 吗?

不一定。它只说明该窗口步骤需要排序,还要结合排序键、输入规模和整体访问路径判断。

多个窗口对象是不是就代表执行了多个全量排序?

不能这样直接推断。排序要求相同的窗口可能连续处理并复用顺序,应比较每个对象的分区和排序字段。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
JSON 路径索引 怎样减少文档扫描JSON 路径索引 怎样减少文档扫描
上一篇
JSON 路径索引 怎样减少文档扫描
部分更新 怎样减少 JSON 写放大
下一篇
部分更新 怎样减少 JSON 写放大
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    683次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    699次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    748次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    714次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    551次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码