当前位置: 首页 > news >正文

SQL 调优第一步:EXPLAIN 关键字全解析

目录

一、Explain核心概念

二、实战 

2.1 简述功能

🔍什么是查询块?

 2.2 详细解析

2.2.1 id--查询块的唯一序号

2.2.2 select_type--该查询块的类型

2.2.3  table--本次访问的表(或别名)

2.2.4 type--访问方式(性能等级)

2.2.5 possible_keys--可供选择的索引列表

2.2.6 key--实际使用的索引

2.2.7 key_len--所用索引的字节长度

2.2.8 ref--与索引列等值匹配的列或常量

2.2.9 rows--预估需扫描的行数

2.2.10 Extra--额外执行信息


一、Explain核心概念

使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,而不是直接运行,开发者就可以通过对模拟的分析再决定是加索引、改写 SQL,还是调整表结构。

🧠根据对explain结果的分析,可以得到以下结果:

  1. 全表的读取顺序id + table:决定多表 JOIN 时先读哪张表、后读哪张表。

  2. 数据读取操作的操作类型type:system / const / ref / range / ALL 等。

  3. 哪些索引可以使用possible_keys:优化器候选索引列表。

  4. 哪些索引被实际使用key:真正被采用的索引。

  5. 表之间的引用ref:显示当前表用到了哪张表的哪一列做等值匹配。

  6. 每张表有多少行被优化器查询rows:估计要扫描的行数。 

二、实战 

2.1 简述功能

字段代表含义
id查询块的唯一序号
select_type该查询块的类型
table本次访问的表(或别名)
type访问方式(性能等级)
possible_keys可供选择的索引列表
key实际使用的索引
key_len所用索引的字节长度
ref与索引列等值匹配的列或常量
rows预估需扫描的行数
Extra额外执行信息

🔍什么是查询块?

 查询块 = 语句树中每个独立 SELECT 的小节点。EXPLAIN 的 id 就是给这些节点按出现的先后顺序编号。

场景示例包含几个查询块
SELECT * FROM t_student;1
SELECT * FROM t_student WHERE id IN (SELECT id FROM t_score);2(外层 1,子查询 1)
SELECT * FROM t1 UNION SELECT * FROM t2;2(每个 UNION 分支 1)
SELECT * FROM (SELECT * FROM t_student) AS s;2(派生表 1,外层 1)

 2.2 详细解析

可以看出调用这个SQL语句后,得到了下面的行元素值,下面逐一分析:

2.2.1 id--查询块的唯一序号

💡详细说明

  • 每个 SELECT 语句都会被分配一个唯一的 id

  • 数字越大,执行顺序越靠前

  • id 相同表示这些查询块是同一级别的,执行顺序由上至下

  • id 为 NULL 表示这是一个结果集,不需要使用它来进行查询

2.2.2 select_type--该查询块的类型

💡详细说明

  • SIMPLE:简单查询(不包含子查询或 UNION)

  • PRIMARY:最外层的查询

  • SUBQUERY:子查询中的第一个 SELECT

  • DERIVED:派生表(FROM 子句中的子查询)

  • UNION:UNION 中第二个及以后的 SELECT

  • UNION RESULT:UNION 的结果

  • DEPENDENT SUBQUERY:依赖于外部查询的子查询

  • UNCACHEABLE SUBQUERY:结果不能被缓存的子查询

2.2.3  table--本次访问的表(或别名)

💡详细说明

  • 显示表名或表的别名
  • 如果是派生表,会显示为 <derivedN>,其中 N 是 id 值

  • 如果是 UNION 结果,会显示为 <unionM,N,...>

2.2.4 type--访问方式(性能等级)

💡详细说明(从最优到最差排序):

  • system:表只有一行记录(系统表)

  • const:通过主键或唯一索引一次就找到

  • eq_ref:关联查询中,使用主键或唯一索引关联

  • ref:使用非唯一索引扫描或唯一索引前缀扫描

  • fulltext:使用全文索引

  • ref_or_null:类似 ref,但包含 NULL 值的查询

  • index_merge:使用了索引合并优化

  • unique_subquery:IN 子查询中使用唯一索引

  • index_subquery:IN 子查询中使用非唯一索引

  • range:索引范围扫描

  • index:全索引扫描

  • ALL:全表扫描(最差情况)

2.2.5 possible_keys--可供选择的索引列表

💡详细说明

  • 显示可能应用在这张表中的索引

  • 如果为 NULL,则表示没有可用的索引

  • 实际查询时可能不会使用这些索引

2.2.6 key--实际使用的索引

💡详细说明

  • 显示 MySQL 实际决定使用的索引

  • 如果为 NULL,则表示没有使用索引

  • 可能出现在 possible_keys 中,也可能不出现(MySQL 优化器自行判断)

2.2.7 key_len--所用索引的字节长度

💡详细说明

  • 表示索引中使用的字节数

  • 可计算查询中使用的索引长度(越短越好)

  • 对于复合索引,可以判断使用了哪些部分

2.2.8 ref--与索引列等值匹配的列或常量

💡详细说明

  • 显示索引的哪一列被使用了

  • 可能是一个常量(const)、列名或函数

  • 如果为 NULL,表示没有引用

2.2.9 rows--预估需扫描的行数

💡详细说明

  • MySQL 估计为了找到所需的行而要读取的行数

  • 是一个预估值,不是精确值

  • 对于 InnoDB 表,这个数字是估计值

2.2.10 Extra--额外执行信息

💡常见值及说明

  • Using index:使用了覆盖索引(只需索引就能获取数据)

  • Using where:在存储引擎检索后再过滤

  • Using temporary:需要使用临时表

  • Using filesort:需要额外排序操作

  • Using join buffer:使用了连接缓存

  • Impossible WHERE:WHERE 子句始终为 false

  • Select tables optimized away:通过索引优化,可能不需要访问表

http://www.lryc.cn/news/594175.html

相关文章:

  • [Java恶补day44] 整理模板·考点七【二叉树】
  • Docker Desktop 入门教程(Windows macOS)
  • HTTP 进化史:从 1.0 到 3.0
  • The FastMCP Client
  • 你的created_time字段,用DATETIME还是TIMESTAMP?
  • Python自动化测试项目实战
  • Python 模块与包导入 基础讲解
  • Haproxy算法精简化理解及企业级高功能实战
  • 如何在看板中体现任务依赖关系
  • Windows CMD(命令提示符)中最常用的命令汇总和实战示例
  • 让黑窗口变彩色:C++控制台颜色修改指南
  • 30天打牢数模基础-SVM讲解
  • Linux操作系统从入门到实战(十一)回车换行问题与用户缓冲区问题
  • 内网后渗透攻击过程(实验环境)--3、横向攻击
  • dify创建OCR工作流
  • java抗疫物质管理系统设计和实现
  • 多人在线场景下Three.js同步机制设计:延迟补偿、状态插值的工程实践
  • 07_图像容器Mat_详解
  • 元学习算法的数学本质:从MAML到Reptile的理论统一与深度分析
  • maven构建Could not transfer artifact失败原因
  • 红宝书单词学习笔记 list 51-75
  • Word for mac使用宏
  • Function Callingの进化路:源起篇
  • Node.js Express keep-alive 超时时间设置
  • 基于Pytorch的人脸识别程序
  • 【JS逆向基础】数据库之redis
  • 华为开源自研AI框架昇思MindSpore应用案例:基于ERNIE模型实现对话情绪识别
  • 对于stm32RCT6的外部中断
  • `tidyverse` 中涉及的函数及其用法
  • tabBar设置底部菜单选项、iconfont图标(图片)库、模拟京东app的底部导航栏