文章目录

  • 一、MySQL EXPLAIN ANALYZE 执行计划指南
    • 主要功能
      • 实际执行性能分析
      • 详细的执行统计
      • 性能瓶颈识别
    • 与普通 EXPLAIN 的区别
    • 使用场景
      • 查询优化
      • 问题诊断
    • 总结
  • 二、EXPLAIN ANALYZE 执行计划
    • 样例
    • 分析
      • 执行顺序解读
      • 逐行详细解释
        • 第 7 行 (最内层)
        • 第 6 行
        • 第 5 行
        • 第 4 行
        • 第 3 行
        • 第 2 行
        • 第 1 行 (最外层)
      • 总结与性能分析


一、MySQL EXPLAIN ANALYZE 执行计划指南

MySQL 的 EXPLAIN ANALYZE 是一个强大的查询分析工具,它提供了比传统 EXPLAIN 更详细的查询执行信息。

主要功能

实际执行性能分析

  • 不仅显示预估的执行计划,还会实际执行查询并收集真实的性能数据
  • 提供每个操作的实际执行时间、处理行数等精确信息

详细的执行统计

  • 显示每个步骤的实际成本(actual cost)
  • 提供实际处理的行数与估计行数的对比
  • 展示每个操作的实际执行时间

性能瓶颈识别

  • 快速定位查询中最耗时的操作
  • 识别全表扫描、不必要的排序等性能问题
  • 找出索引使用不当的情况

与普通 EXPLAIN 的区别

EXPLAIN 只是分析执行计划而不实际执行查询,而 EXPLAIN ANALYZE 会真正执行查询,因此:

  • 提供更准确的性能数据
  • 能发现优化器估算错误的情况
  • 但执行时间会更长,特别是对于复杂查询

使用场景

查询优化

  • 对比不同索引策略的实际效果
  • 验证查询重写是否真正提升性能
  • 分析复杂 JOIN 查询的执行效率

问题诊断

  • 排查慢查询的根本原因
  • 识别数据分布不均匀导致的性能问题
  • 发现统计信息过时的情况

总结

EXPLAIN ANALYZE 是数据库性能调优和查询优化的重要工具,能帮助你从估算转向基于实际数据的优化决策。通过提供真实的执行统计信息,它让数据库性能分析更加准确和可靠。


二、EXPLAIN ANALYZE 执行计划

样例

-> Sort: <temporary>.Population DESC (actual time=8.306..8.431 rows=125 loops=1)-> Stream results (actual time=0.145..8.033 rows=125 loops=1)-> Nested loop inner join (cost=241.12 rows=205) (actual time=0.141..7.787 rows=125 loops=1)-> Filter: (world.country.Continent = 'Asia') (cost=25.40 rows=34) (actual time=0.064..0.820 rows=51 loops=1)-> Table scan on country (cost=25.40 rows=239) (actual time=0.059..0.359 rows=239 loops=1)-> Filter: (world.city.Population > 1000000) (cost=4.53 rows=6) (actual time=0.030..0.131 rows=2 loops=51)-> Index lookup on city using CountryCode (CountryCode=world.country.`Code`) (cost=4.53 rows=18) (actual time=0.023..0.096 rows=35 loops=51)

分析

我们来详细解读这个 MySQL 的 EXPLAIN ANALYZE 执行计划。

这个执行计划展示了数据库为了执行一个查询而采取的具体步骤、成本估算以及(因为有 actual time)实际的执行时间和处理行数。

首先,根据执行计划我们可以推断出原始的 SQL 查询大致是这样的:

EXPLAIN ANALYZE
SELECT-- ... some columns from city and country
FROMcity
INNER JOINcountry ON city.CountryCode = country.Code
WHEREcountry.Continent = 'Asia'AND city.Population > 1000000
ORDER BYcity.Population DESC;

执行顺序解读

数据库执行计划的读取顺序是 从内到外,从上到下。也就是说,缩进最深的步骤最先执行。执行流程如下:

  1. 扫描 country 表 (Line 5)
  2. 过滤出 Continent = 'Asia' 的国家 (Line 4)
  3. 对于每一个亚洲国家,去 city 表中查找对应的城市 (Line 7)
  4. 过滤出人口大于一百万的城市 (Line 6)
  5. 将上面两步(3和4)组合成一个嵌套循环连接 (Line 3)
  6. 将连接后的结果进行流式处理 (Line 2)
  7. 对最终结果按 Population 降序排序 (Line 1)

逐行详细解释

第 7 行 (最内层)
-> Index lookup on city using CountryCode (CountryCode=world.country.`Code`) (cost=4.53 rows=18) (actual time=0.023..0.096 rows=35 loops=51)
  • 操作: Index lookup on city using CountryCode
    • 含义: 这是嵌套循环的内层操作。数据库正在使用 city 表上的 CountryCode 索引来查找与外层(country 表)匹配的行。连接条件是 city.CountryCode = country.Code
  • 成本估算: (cost=4.53 rows=18)
    • 含义: 优化器估计每次执行这个查找操作的成本是 4.53,并且估计平均每次能找到 18 行。
  • 实际执行: (actual time=0.023..0.096 rows=35 loops=51)
    • actual time=0.023..0.096: 第一次执行此操作耗时 0.023 毫秒,所有执行中最长的一次耗时 0.096 毫秒。
    • rows=35: 实际上平均每次查找返回了 35 行。这说明优化器的估计(18行)偏低了。
    • loops=51: 这个操作被执行了 51 次。这非常关键,它告诉我们上一步(过滤国家)产生了 51 行结果。
第 6 行
-> Filter: (world.city.Population > 1000000) (cost=4.53 rows=6) (actual time=0.030..0.131 rows=2 loops=51)
  • 操作: Filter: (world.city.Population > 1000000)
    • 含义: 对上一步(Index lookup)返回的城市结果进行过滤,只保留人口 (Population) 大于 1,000,000 的城市。
  • 成本估算: (cost=4.53 rows=6)
    • 含义: 优化器估计在找到的城市中,平均有 6 个城市的人口会超过一百万。
  • 实际执行: (actual time=0.030..0.131 rows=2 loops=51)
    • rows=2: 实际上平均每次只有 2 个城市满足人口条件。
    • loops=51: 这个过滤操作同样被执行了 51 次,与上一步的循环次数一致。
第 5 行
-> Table scan on country (cost=25.40 rows=239) (actual time=0.059..0.359 rows=239 loops=1)
  • 操作: Table scan on country
    • 含义: 这是嵌套循环的外层驱动操作的起点。数据库正在执行全表扫描,即读取 country 表中的每一行。
  • 成本估算: (cost=25.40 rows=239)
    • 含义: 优化器估计全表扫描的成本是 25.40,并估计 country 表总共有 239 行。
  • 实际执行: (actual time=0.059..0.359 rows=239 loops=1)
    • rows=239: 实际上确实扫描了 239 行。
    • loops=1: 这个全表扫描操作只执行了 1 次。
第 4 行
-> Filter: (world.country.Continent = 'Asia') (cost=25.40 rows=34) (actual time=0.064..0.820 rows=51 loops=1)
  • 操作: Filter: (world.country.Continent = 'Asia')
    • 含义: 对上一步(全表扫描)的结果进行过滤,只保留 Continent 字段为 ‘Asia’ 的国家。
  • 成本估算: (cost=25.40 rows=34)
    • 含义: 优化器估计会有 34 个亚洲国家。
  • 实际执行: (actual time=0.064..0.820 rows=51 loops=1)
    • rows=51: 实际上找到了 51 个亚洲国家。这个数字(51)成为了内层循环(Index lookupFilter)的 loops 次数。
    • loops=1: 这个过滤操作也只执行了 1 次。
第 3 行
-> Nested loop inner join (cost=241.12 rows=205) (actual time=0.141..7.787 rows=125 loops=1)
  • 操作: Nested loop inner join
    • 含义: 这是一个总结行,表示数据库使用了嵌套循环连接算法。它将上面两个分支(过滤后的 country 表和过滤后的 city 表)的结果连接起来。
  • 成本估算: (cost=241.12 rows=205)
    • 含义: 优化器估计整个连接操作的总成本是 241.12,最终会产生 205 行结果。
  • 实际执行: (actual time=0.141..7.787 rows=125 loops=1)
    • rows=125: 实际上,整个连接操作最终产生了 125 行结果(51个亚洲国家中,总共有125个城市人口超百万)。
    • loops=1: 整个连接过程作为一个整体,执行了 1 次。
第 2 行
-> Stream results (actual time=0.145..8.033 rows=125 loops=1)
  • 操作: Stream results
    • 含义: 这是一个中间步骤,将连接操作产生的 125 行结果以流的形式传递给下一个操作(排序)。
  • 实际执行: (actual time=... rows=125 loops=1)
    • 它处理了 125 行数据,耗时反映了从接收第一行到传递完最后一行的时间。
第 1 行 (最外层)
-> Sort: <temporary>.Population DESC (actual time=8.306..8.431 rows=125 loops=1)
  • 操作: Sort: <temporary>.Population DESC
    • 含义: 这是查询的最后一步。数据库对前序步骤传来的 125 行结果,按照 Population 字段进行降序排序 (DESC)。
    • <temporary>: 这个标记意味着 MySQL 需要使用一个临时表(可能在内存或磁盘上)来完成排序操作。这通常发生在 ORDER BY 的字段没有可用索引时。
  • 实际执行: (actual time=8.306..8.431 rows=125 loops=1)
    • actual time: 从开始接收数据到排序完成并输出最后一行,总共耗时约 8.431 毫秒。这是整个查询的主要耗时部分。
    • rows=125: 排序了 125 行数据。

总结与性能分析

  1. 连接策略: 查询使用了 Nested Loop Join。对于外层结果集不大(51行)的情况,这是一个合理的选择。
  2. 外层扫描: 对 country 表进行了全表扫描。由于该表只有 239 行,这几乎没有性能影响。如果 country 表非常大,那么在 Continent 字段上建立索引将是首要的优化点。
  3. 内层查找: 对 city 表的查找使用了 CountryCode 索引,这是非常高效的。
  4. 排序: 查询的最后一步是排序,并且使用了临时表。这是因为结果集是动态生成的,无法利用现有索引来避免排序。这是查询总耗时的主要来源。
  5. 优化器估算: 优化器在行数估算上存在一些偏差(如亚洲国家34 vs 51,每个国家的城市数18 vs 35),但这些偏差没有导致选择错误的执行计划。
  6. 潜在优化: 如果要进一步优化,可以考虑在 city 表上创建一个复合索引 (CountryCode, Population)。这样数据库可以在索引层面就完成对 Population > 1000000 的过滤,减少从磁盘读取的数据页,可能会略微提升性能。

文章如有问题,请彦祖帮忙指正!感激不尽!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913601.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913601.shtml
英文地址,请注明出处:http://en.pswp.cn/news/913601.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Google I/O Extended :2025 Flutter 的现状与未来

大家好&#xff0c;我是 Flutter GDE 郭树煜&#xff0c;Github GSY 项目的维护人&#xff0c;今天主要分享的内容是「Flutter 的现状与未来」&#xff0c;可能今天更多会是信息科普类型的内容&#xff0c;主要是分享关于 Flutter 的现状与未来 现状 其实 Flutter 从开源到现在…

软考(软件设计师)数据库原理:事务管理,备份恢复,并发控制

数据库事务管理与备份恢复 事务&#xff08;Transaction&#xff09; 是数据库管理系统中执行的一个不可分割的工作单元&#xff0c;它包含一组 SQL 操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部不执行。 事务的四大特性&#xff08;ACID&#xff09;&…

【牛客刷题】相遇

文章目录 一、题目介绍1.1 题目描述1.2 输入描述1.3 输出描述1.4 示例二、解题思路2.1 核心算法设计2.2 性能优化关键2.3 算法流程图三、解法实现3.1 解法一:基础实现3.1.1 初级版本分析3.2 解法二:优化版本(推荐)3.2.1 优化版本分析一、题目介绍 1.1 题目描述 街道可以看…

uni-app 下拉搜索多选 支持自己创建数据

组件 /components/selectmul.vue <template><view class="multi-select-container"><view class="input-dropdown-container"><view class="" v-if="selectlist&&selectlist[0]"><text class=&qu…

nmon使用方法

安装方法 方法1&#xff1a; 最简单方法&#xff1a; #dnf install nom 验证 执行命令&#xff1a; #nmon 方法2&#xff1a; 下载安装包安装&#xff0c;下载地址 官网&#xff1a;nmon and njmon | Site / Download 或者&#xff1a;https://sourceforge.net/project…

Google AI 刚刚开源 MCP 数据库工具箱,让 AI 代理安全高效地查询数据库

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

数学建模的一般步骤

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 青春由磨砺而出彩&#xff0c;人生因奋…

【web安全】SQLMap 参数深度解析:--risk 与 --level 详解

目录 简介 一、--risk 参数&#xff1a;测试风险控制 1. 基本定义 2. 各级别详细对比 risk1 (默认) risk2 risk3 3. 使用建议 二、--level 参数&#xff1a;测试深度控制 1. 基本定义 2. 各级别详细对比 level1 (默认) level2 level3 level4 level5 3. 技术实…

YOLO在自动驾驶交通标志识别中的应用与优化【附代码】

文章目录YOLO在自动驾驶交通标志识别中的应用与优化引言1. YOLO算法概述1.1 YOLO的核心思想1.2 YOLO的演进2. 交通标志识别的挑战2.1 数据集特性2.2 性能指标要求3. YOLO模型优化策略3.1 数据增强改进3.2 注意力机制集成3.3 针对小目标的改进4. 完整实现示例4.1 模型训练代码4.…

开源鸿蒙(OpenHarmony)桌面版全面解析:架构适配、设备支持与开发实战

摘要:深度剖析OpenHarmony 4.0+桌面版的技术演进,揭秘其在X86/国产芯片设备的落地实践,附源码获取与开发板实战指南 一、OpenHarmony桌面版架构突破 1.1 跨平台内核适配 开源鸿蒙通过 多内核混合架构 实现全场景覆盖: X86架构:集成Linux内核适配层(kernel/linux),支持…

【WEB】Polar靶场 11-15题 详细笔记

目录 十一.爆破 PHP的基本语法 变量与常量 数据类型 流程控制 函数 文件操作 数据库交互 1.substr() 函数 2. intval() 函数 十二.XFF X-Forwarded-For&#xff08;简称XFF&#xff09; 十三.rce1 shell 命令分隔符 isset()函数 preg_match_all()函数 ${IFS}…

导诊系统的科室和症状词库如何扩展?

要扩展导诊系统的科室和症状词库&#xff0c;可以通过以下几种方式实现&#xff1a;1. 直接扩展科室定义&#xff08;推荐&#xff09;在初始化代码中直接添加新的科室及对应症状&#xff1a;# 扩展后的科室定义 depts [Department("内科", ["发热", &quo…

通过Prompt生成互动式网页HTML案例探索(二)

之前提到了一些【通过Claude 生成图片的prompt集锦&#xff08;一&#xff09;】&#xff0c;本篇沿着试着用prompt生成互动式网页 文章目录 1 什么是互动式网页&#xff1f;1.1 一个&#x1f330;1.1 核心能力列举1.3 部署方式 2 猜测秘塔AI搜索生成HTML的Prompt3 mozi大佬&am…

暑假读书笔记第四天

今日文章&#xff1a; 小林coding&#xff1a;什么是软中断&#xff1f; 目录软中断软中断概述软中断类型如何定位软中断 CPU 使用率过高的问题&#xff1f;其他: 往期打卡 软中断 中断是系统用来响应硬件设备请求的一种机制&#xff0c;操作系统收到硬件的中断请求&#xf…

跨平台的ARM 和 x86 Docker 镜像:汇编语言实验环境搭建

一、安装和配置 Docker 1.安装 Docker 官网链接&#xff1a;https://www.docker.com/ 以Debian(Ubuntu)系统为例: #安装依赖包 sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg lsb-release#添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyr…

【前端知识】HTML页面渲染:底层原理与技术实现剖析

HTML页面渲染&#xff1a;底层原理与技术实现剖析HTML页面渲染&#xff1a;底层原理与技术实现剖析渲染引擎的核心工作流程深度解析渲染关键阶段1. 解析与构建DOM&#xff08;Document Object Model&#xff09;2. 构建CSSOM&#xff08;CSS Object Model&#xff09;3. 渲染树…

Catmull-Rom平滑多段线在奇异点处的扭曲问题(1)

Catmull-Rom在奇异点处的扭曲问题 引言 在计算机图形学和动画中&#xff0c;我们经常需要在已知点之间创建平滑的过渡。Catmull-Rom样条是一种流行的插值方法&#xff0c;它以简单直观的方式生成经过所有控制点的平滑曲线。本文将深入探讨Catmull-Rom插值的原理、实现和应用。…

SX8652IWLTRT Semtech升特超低功耗触控芯片 12通道+I²C接口 重新定义人机交互!

SX8652IWLTRT&#xff08;Semtech&#xff09;产品解析与推广文案一、产品定位SX8652IWLTRT是Semtech&#xff08;升特半导体&#xff09;推出的低功耗电容式触摸控制器&#xff0c;采用IC接口&#xff0c;专为便携式设备和小家电的触摸交互设计&#xff0c;支持多点触控和手势…

第02章 MySQL环境搭建

1.MySQL的卸载 步骤1&#xff1a;停止MySQL服务 在卸载之前&#xff0c;先停止MySQL8.0的服务。按键盘上的“Ctrl Alt Delete”组合键&#xff0c;打开“任务管理器”对话框&#xff0c;可以在“服务”列表找到“MySQL8.0”的服务&#xff0c;如果现在“正在运行”状态&#…

实战Linux进程状态观察:R、S、D、T、Z状态详解与实验模拟

前言 在Linux系统中&#xff0c;进程状态是系统管理和性能调优的核心知识。一个进程从诞生到终止&#xff0c;会经历运行&#xff08;R&#xff09;、可中断睡眠&#xff08;S&#xff09;、不可中断睡眠&#xff08;D&#xff09;、停止&#xff08;T&#xff09;、僵尸&#…