让MySQL更快:EXPLAIN语句详尽解析

news2025/5/28 1:51:09

前言

在数据库性能调优中,SQL 查询的执行效率是影响系统整体性能的关键因素之一。MySQL 提供了强大的工具——EXPLAIN 语句,帮助开发者和数据库管理员深入分析查询的执行计划,从而发现潜在的性能瓶颈并进行针对性优化。

EXPLAIN 语句能够模拟 MySQL 优化器的执行过程,返回查询的详细执行计划,包括表的访问顺序、索引的使用情况、连接类型、扫描行数等关键信息。通过理解 EXPLAIN 的输出,开发者可以快速定位低效查询的问题所在,例如全表扫描、缺少索引、临时表或文件排序等,并采取相应的优化措施。

本文将详细介绍 EXPLAIN 的基本用法、输出字段的含义,并通过实际案例演示如何利用 EXPLAIN 分析和优化 SQL 查询。

微信图片_20250524153711

一、关于EXPLAIN语句

1.1 简介

EXPLAIN 是 MySQL 提供的用于分析 SQL 查询执行计划的工具。它通过在 SELECT 语句前添加 EXPLAIN 关键字,使 MySQL 返回查询的执行计划,而不是实际执行查询。执行计划描述了 MySQL 如何访问表、如何使用索引以及如何连接表等信息。

EXPLAIN 的主要作用包括:

  • 分析查询性能:识别慢查询的根源,例如全表扫描或索引未命中。
  • 验证索引有效性:确认是否正确使用了索引,或者是否需要添加新的索引。
  • 优化查询结构:调整查询语句或表结构以提高执行效率。

1.2 语法

EXPLAIN 的基本语法如下:

EXPLAIN [EXTENDED] [FORMAT = {TRADITIONAL | JSON}] SELECT ...;  
  • EXTENDED:扩展输出,显示更多信息(如优化后的查询语句)。
  • FORMAT = JSON:以 JSON 格式返回结果,便于解析和调试。

示例

在select前加explain关键字,MySQL会返回该查询的执行计划而不是执行这条SQL

mysql> explain select * from student where id=1;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set

image

二、Explain列的含义

EXPLAIN 的输出结果包含多个字段,每个字段提供了不同的信息。以下是关键字段的详细说明:

2.1 概览

以下是 MySQL EXPLAIN输出列的详细说明,包括每列的定义、示例值、优化目标及判断标准,帮助你深入理解查询执行计划:

列名作用描述优化目标(好的输出特征)
id查询的执行顺序标识符子查询或复杂查询时,id 值高的先执行
select_type查询类型(简单查询、子查询、UNION 等)SIMPLE​ 或 PRIMARY​ 表示简单或主查询
table当前操作的表名(包括临时表或派生表)表名清晰,避免过多 <derived>​ 或 <union>
partitions匹配的分区(若表有分区)分区裁剪合理,避免全分区扫描
type数据访问方式(关键性能指标)const​、eq_ref​、ref​、range​ 优于 ALL
possible_keys可能用到的索引包含实际使用的索引
key实际使用的索引明确显示有效索引名,非 NULL
key_len索引使用的字节数与索引字段长度匹配,避免未完全使用索引
ref与索引比较的列或常量const​ 或关联字段,避免 NULL
rows预估扫描的行数(估算值)数值越小越好
filtered查询条件过滤后剩余行的百分比百分比高(接近 100%)
Extra额外执行信息(关键优化提示)出现 Using index​,避免 Using filesort

2.2 每列详细说明及优化建议

1. id

  • 含义:查询的标识符,表示查询中 SELECT​ 子句的执行顺序。
    查询的序列号,标识执行顺序。相同 id​ 按从上到下执行;不同 id​ 时,值大的先执行(如子查询)。

  • 示例

    EXPLAIN SELECT * FROM (SELECT * FROM t1) AS t_derived JOIN t2 ON t1.id = t2.id;
    
    • id=1​:派生表 t_derived​(子查询)。
    • id=1​:主查询 t2​。
  • 优化目标
    避免多层嵌套子查询(id​ 过多),减少复杂查询。

  • 单一查询(无子查询或 UNION​)时,id​ 为 1​。

  • 复杂查询中,id​ 的层级清晰,避免嵌套过深。

2. select_type

  • 含义:查询的类型,描述查询的复杂度。

  • |常见值及优化建议:|||

    说明理想情况
    SIMPLE简单查询,不包含子查询或 UNION​。最佳,避免复杂嵌套。
    PRIMARY最外层查询。正常,需关注其依赖的子查询。
    SUBQUERY子查询中的第一个 SELECT​。尽量避免,可考虑改写为连接查询。
    DEPENDENT SUBQUERY子查询依赖外部查询结果。高风险,可能导致性能下降。
    UNIONUNION​ 中的第二个或后续查询。正常,需注意 UNION​ 结果集。
    UNION RESULTUNION​ 的结果集。正常,需检查是否需要额外处理。
    DERIVED派生表(FROM​ 子句中的子查询)。需检查派生表的性能。
    MATERIALIZED物化子查询(MySQL 8.0+)。正常,但需确认物化效果。

3. table

  • 含义:当前查询涉及的表名。

  • 理想输出

    • 表名明确,避免派生表(如 <derivedN>​)或临时表(如 <union1,2>​)。
    • 若出现派生表,需检查子查询是否可优化为连接查询。

4. partitions

  • 含义:查询涉及的分区(如果表是分区表)。

    表示查询涉及的分区情况。当表是分区表时,这个列会显示匹配的分区。例如,一个表按照日期字段进行分区,查询中指定了日期范围,那么 partitions 列就会显示涉及到的分区编号或者分区名称。

  • 理想输出

    • 分区表中仅扫描相关分区(如 p1​),而非全表扫描。

    • 若为 NULL​,表示表未分区或未使用分区。

      如果表是分区表,希望 partitions 列显示的分区范围尽量小。这样可以减少查询需要扫描的数据量,提高查询效率。例如,如果一个分区表有 100 个分区,而查询只涉及到其中的 1 - 2 个分区,这就是比较理想的输出。

5. type

  • 含义:连接类型(访问方法),反映 MySQL 如何查找表中的行。

  • 性能排序(从优到劣)

    1. system:表仅一行(系统表),是 const​ 的特例。
    2. const:通过主键或唯一索引等值查询,最多匹配一行。
    3. eq_ref:使用主键或唯一索引进行等值连接(如 JOIN​)。
    4. ref:使用非唯一索引进行等值查询。
    5. range:索引范围查询(如 BETWEEN​、>​、<​)。
    6. index:全索引扫描(比全表扫描快)。
    7. ALL:全表扫描(最差)。
  • 优化建议

    • 目标是达到 const​、eq_ref​ 或 ref​。
    • 避免 ALL​,需添加索引或优化查询条件。

6. possible_keys

  • 含义:可能使用的索引(候选索引)。

  • 理想输出

    • 显示多个候选索引(说明索引设计合理)。

    • 若为 NULL​,表示无可用索引,需添加索引。

      列出与查询条件相关的索引。

7. key

  • 含义:实际使用的索引。如果 key​ 为 NULL​,表示没有使用索引,可能是全表扫描。

  • 理想输出

    • 明确显示使用的索引(如 idx_name​)。
    • 若为 NULL​,表示未使用索引,需检查 possible_keys​ 并优化索引。
    • 显示与 possible_keys​ 中相同的索引,说明 MySQL 选择了合适的索引。

8. key_len

  • 含义:使用的索引长度(字节数)。

  • 理想输出

    • 值越小越好(表示使用的索引列越少或数据类型更紧凑)。
    • 例如,VARCHAR(100)​ 使用 utf8mb4​ 编码时,最大占用 400​ 字节。

9. ref

  • 含义:显示索引的哪一列被使用,以及与之比较的值(常量或列名)。

    • 显示哪些列或常量被用于查找索引列上的值。常见值包括:

    const​:使用常量值。

    表的列名:使用其他表的列进行比较。

  • func​:使用函数结果。

  • 理想输出

    • 显示具体的列名或常量(如 const​),表明索引有效。
    • 若为 func​ 或 NULL​,可能表示索引未正确使用。
    • 显示具体的列名或常量,表明索引被有效利用。

10. rows(估计扫描行数)

  • 含义:MySQL 估计需要扫描的行数。

  • 理想输出

    • 值越小越好(表示过滤条件越精确)。例如,如果一个查询估算只需要检查 10 行就可以得到结果,这比估算检查 10000 行要好得多。这表明查询能够快速定位到所需的数据行。
    • 若值过大(如 100000​),需优化索引或查询条件。

11. filtered

  • 含义:表示查询条件过滤的行百分比(MySQL 5.7+)。该值表示查询扫描的行中有多少被筛选掉,值的范围是 0 到 100。

    • 表示在存储引擎返回的行中,经过 MySQL 服务器层过滤后,实际满足查询条件的行的比例。它是基于表统计信息和索引统计信息的一个估算值。
  • 理想输出

    • 值越高越好(如 100%​ 表示无过滤条件)。
    • 若值较低(如 10%​),说明查询条件未充分利用索引。
    • filtered 的值应该尽可能高。例如,如果 filtered 的值是 90%,意味着存储引擎返回的行中有 90% 的行满足查询条件,这比 filtered 值为 10% 的情况要好,因为减少了不必要的数据处理。

12. Extra

  • 含义:额外信息,提供查询执行的附加说明,帮助诊断查询执行的细节
  • |常见值及优化建议:|||
    说明优化建议
    Using index使用覆盖索引(查询列全部命中索引)。无需回表,性能最佳。
    Using where使用 WHERE​ 条件过滤数据。正常,但需检查过滤条件效率。
    Using temporary需要创建临时表(如 ORDER BY​ 和 GROUP BY​ 一起使用)。避免,优化查询或添加索引。
    Using filesort需要额外排序操作(如 ORDER BY​ 未使用索引)。避免,优化排序字段索引。
    Distinct优化了 DISTINCT​ 查询。正常,无需额外优化。
    Range checked for each record未找到合适索引,需逐行检查。添加合适索引。

  • 良好输出:希望出现像 “Using index” 这样的提示,这表明查询效率较高。尽量避免出现 “Using temporary” 和 “Using filesort”,因为它们表示需要额外的资源开销来处理查询,如临时表和文件排序,这可能会降低查询性能。

三、优化建议及示例

3.1 优化建议

  1. 关注 type:确保查询达到 const​、eq_ref​ 或 ref​ 级别,避免 ALL​。
  2. 优化 Extra:避免 Using filesort​ 和 Using temporary​。
  3. 分析 key possible_keys​:确认是否使用了预期的索引。
  4. 减少扫描行数:通过索引或优化查询条件降低 rows​ 值。
  5. 检查 filtered​:确保过滤条件有效,提高查询效率。

3.2 优化示例

全表扫描

场景:全表扫描(type=ALL​)

  • 问题 SQL

    EXPLAIN SELECT * FROM users WHERE phone = '123456789';
    
  • 输出type=ALL​,key=NULL​。

  • 优化:为 phone​ 字段添加索引:

    ALTER TABLE users ADD INDEX idx_phone(phone);
    
  • 优化后输出type=ref​,key=idx_phone​,rows=1​。

多表连接优化(Using join buffer)

问题描述

多表连接时出现 Using join buffer​,性能低下。

原SQL

SELECT u.name, o.order_no 
FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.age > 25 AND o.status = 'completed';

EXPLAIN 分析

EXPLAIN SELECT u.name, o.order_no FROM users u JOIN orders o ON u.id = o.user_id WHERE u.age > 25 AND o.status = 'completed';

输出结果

id | select_type | table | type | possible_keys | key        | rows | Extra
---|-------------|-------|------|---------------|------------|------|-------------------
1  | SIMPLE      | u     | ALL  | idx_age       | NULL       | 1000 | Using where
1  | SIMPLE      | o     | ref  | idx_user_id   | idx_user_id| 500  | Using where; Using join buffer (Block Nested Loop)

问题诊断

  • users 表 type=ALL:未使用索引,全表扫描。
  • orders 表 Using join buffer:连接时未使用索引,性能差。

优化方案

  1. users.age创建索引

    ALTER TABLE users ADD INDEX idx_age (age);
    
  2. orders.user_id orders.status创建索引

    ALTER TABLE orders ADD INDEX idx_user_id_status (user_id, status);
    
  3. 调整查询

    SELECT u.name, o.order_no 
    FROM users u 
    JOIN orders o ON u.id = o.user_id 
    WHERE u.age > 25 AND o.status = 'completed';
    
  4. 验证优化效果

    EXPLAIN SELECT u.name, o.order_no FROM users u JOIN orders o ON u.id = o.user_id WHERE u.age > 25 AND o.status = 'completed';
    

    优化后输出

    id | select_type | table | type | possible_keys         | key                  | rows | Extra
    ---|-------------|-------|------|-----------------------|----------------------|------|---------
    1  | SIMPLE      | u     | range| idx_age               | idx_age              | 500  | Using where
    1  | SIMPLE      | o     | ref  | idx_user_id_status    | idx_user_id_status   | 200  | Using where
    

效果

  • users 表 type=range:使用索引范围扫描。
  • orders 表 Using join buffer 消失:连接直接通过索引完成。

结束语

EXPLAIN​语句是MySQL查询优化的核心工具,如同数据库工程师的"听诊器"。通过本文的详细解析,相信您已经掌握了各输出列的精髓。但需要强调的是,真正的优化功力需要在实践中不断积累。建议每次执行重要查询时养成查看执行计划的习惯,结合业务场景灵活运用索引策略、查询重写等手段。记住:优秀的数据库性能不是偶然,而是源于对每个执行细节的精心雕琢。

求点关注-gif动图 138_爱给网_aigei_com

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[CSS3]rem移动适配

前言 什么是移动端适配? 让页面的元素在屏幕尺寸变化时, 同比放大或缩小 移动适配的方案 rem&#xff1a;目前多数企业在用的解决方案 vw/vh&#xff1a;未来的解决方案 rem 体验rem适配 目标: 能够使用rem单位设置网页元素的尺寸 网页效果: 屏幕宽度不同&#xff0c;网…

向量数据库及ChromaDB的使用

什么是向量数据库&#xff1f; 向量数据库&#xff08;Vector Database&#xff09;&#xff0c;也叫矢量数据库&#xff0c;主要用来存储和处理向量数据。 在数学中&#xff0c;向量是有大小和方向的量&#xff0c;可以使用带箭头的线段表示&#xff0c;箭头指向即为向量的方…

CodeBuddy实现pdf批量加密

本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 前言 在信息爆炸的时代&#xff0c;PDF 格式因其跨平台性和格式稳定性&#xff0c;成为办公、学术、商业等领域传递信息的重要载体。从机密合同到个人隐私文档&#xff0c…

运行打印Hello World启动了多少线程?

序言 看网上说阿里二面问到了一个看似最简单且没有标准答案的一个问题&#xff0c;所有学习编程都是从打印hello World开始的&#xff0c;那运行打印启动了多少个线程&#xff1f; 启动了多少线程&#xff1f; 在运行一个简单的 “Hello World” 程序时&#xff0c;启动的线…

java交易所,多语言,外汇,黄金,区块链,dapp类型的,支持授权,划转,挖矿(源码下载)

目前这套主要是运营交易所类型的&#xff0c;授权的会贵点&#xff0c;编译后的是可以直接跑的&#xff0c;图片也修复了&#xff0c;后门也扫了 都是在跑的项目支持测&#xff0c;全开源 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/90887047 更多…

(已开源-CVPR2024) RadarDistill---NuScenes数据集Radar检测第一名

本文介绍一篇Radar 3D目标检测模型&#xff1a;RadarDistill。雷达数据固有的噪声和稀疏性给3D目标检测带来了巨大挑战。在本文中&#xff0c;作者提出了一种新的知识蒸馏(KD)方法RadarDistill&#xff0c;它可以通过利用激光雷达数据来提高雷达数据的表征。RadarDistill利用三…

【MySQL】 数据库基础数据类型

一、数据库简介 1.什么是数据库 数据库&#xff08;Database&#xff09;是一种用于存储、管理和检索数据的系统化集合。它允许用户以结构化的方式存储大量数据&#xff0c;并通过高效的方式访问和操作这些数据。数据库通常由数据库管理系统&#xff08;DBMS&#xff09;管理&…

MongoDB 错误处理与调试完全指南:从入门到精通

在当今数据驱动的世界中&#xff0c;MongoDB 作为最流行的 NoSQL 数据库之一&#xff0c;因其灵活的数据模型和强大的扩展能力而广受开发者喜爱。然而&#xff0c;与任何复杂系统一样&#xff0c;在使用 MongoDB 过程中难免会遇到各种错误和性能问题。本文将全面介绍 MongoDB 的…

【C++】stack,queue和priority_queue(优先级队列)

文章目录 前言一、栈&#xff08;stack&#xff09;和队列&#xff08;queue&#xff09;的相关接口1.栈的相关接口2.队列的相关接口 二、栈&#xff08;stack&#xff09;和队列&#xff08;queue&#xff09;的模拟实现1.stack的模拟实现2.queue的模拟实现 三、priority_queu…

ubuntu中上传项目至GitHub仓库教程

一、到github官网注册用户 1.注册用户 地址&#xff1a;https://github.com/ 2.安装Git 打开终端&#xff0c;输入指令git,检查是否已安装Git 如果没有安装就输入指令 sudo apt-get install git 二、上传项目到github 1.创建项目仓库 进入github主页&#xff0c;点击号…

windows 下用yolov5 训练模型 给到opencv 使用

windows 使用yolov5训练模型&#xff0c;之后opencv加载模型进行推理。 一&#xff0c;搭建环境 安装 Anaconda 二&#xff0c;创建虚拟环境并安装yolov5 conda create -n yolov5 python3.9 -y conda activate yolov5 git clone https://github.com/ultralytics/yolov5 cd …

Spark集群架构解析:核心组件与Standalone、YARN模式深度对比(AM,Container,Driver,Executor)

一、核心组件定义与关系拆解 1. ApplicationMaster&#xff08;AM&#xff09; 定义&#xff1a;YARN 框架中的应用管理器&#xff0c;每个应用程序&#xff08;如 Spark 作业&#xff09;对应一个 AM。职责&#xff1a; 向 YARN 的 ResourceManager 申请资源&#xff08;Con…

Linux Kernel调试:强大的printk(二)

前言 如果你对printk的基本用法还不熟悉&#xff0c;请先阅读&#xff1a; Linux Kernel调试&#xff1a;强大的printk&#xff08;一&#xff09; 上一篇Linux Kernel调试&#xff1a;强大的printk&#xff08;一&#xff09;我们介绍了printk的基础知识和基本用法&#xf…

Kafka Kraft模式集群 + ssl

文章目录 启用集群资源规划准备证书创建相关文件夹配置文件启动各Kafka节点 故障转移测试spring boot集成 启用集群 配置集群时关键就是提前梳理好需要的网络资源&#xff0c;完成对应server.properties文件的配置。在执行前先把这些梳理好&#xff0c;可以方便后面的配置&…

[crxjs]自己创建一个浏览器插件

参考官方 https://crxjs.dev/vite-plugin/getting-started/vue/create-project 按照流程操作会失败的原因 是因为跨域的问题, 在此处添加 server: {host: "localhost",port: 5173,cors: true,headers: {"Access-Control-Allow-Origin": "*",}…

类的设计模式——单例、工厂以及建造者模式

1.单例模式 1.1 饿汉模式 单例模式&#xff1a;一个类只能创建一个对象&#xff0c;这个设计模式可以保证系统中该类只有一个实例&#xff0c;并提供一个访问它的全局访问点&#xff0c;该实例被所有程序模块共享。 饿汉模式指在程序初始化时就创建一个唯一的实例对象。适用…

STM32之看门狗(IWDG)

一、看门狗外设的原理与应用 背景说明 随着单片机的发展&#xff0c;单片机在家用电器、工业自动化、生产过程控制、智能仪器仪表等领域的应用越来越广泛。然而处于同一电力系统中的各种电气设备通过电或磁的联系彼此紧密相连&#xff0c;相互影响&#xff0c;由于运行方式的…

跟着华为去变革 ——读《常变与长青》有感

《常变与长青》&#xff0c;是华为郭平总2024年上市的著作。走进这本书&#xff0c;我们能够清晰看到华为30多年的成长过程和伴随期间的变革历程&#xff1a;从一家设备代理商开始&#xff0c;起步蹒跚&#xff0c;砥砺前行&#xff0c;在闯过一个又一个磨难之后&#xff0c;成…

图像分割技术的实现与比较分析

引言 图像分割是计算机视觉领域中的一项基础技术&#xff0c;其目标是将数字图像划分为多个图像子区域&#xff08;像素的集合&#xff09;&#xff0c;以简化图像表示&#xff0c;便于后续分析和理解。在医学影像、遥感图像分析、自动驾驶、工业检测等众多领域&#xff0c;图…

node.js配置变量

一、下载安装包 1、官网下载 大家可以在官网下载&#xff0c;适合自己电脑以及项目的需要的版本。 二、node.js安装 1、安装 双击下载的安装包文件&#xff0c;通常为 .exe 或 .msi 格式&#xff08;Windows&#xff09;或 .dmg 格式&#xff08;Mac&#xff09;。系统会…