explian分析sql语句详解

本文深入解析SQL执行计划,包括查询类型、表分析、索引选择、查询方式等关键概念,帮助理解如何优化SQL语句,提升数据库性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

explian语句用于分析sql的执行计划,如下

select_type:查询类型

    simple不含子查询 

    primary(含子查询或者派生查询)

    subquery(非from子查询)

    derived(from型子查询)

    union

    union result

table:查询针对的表

    有可能是

    实际的表

    表的别名

    derived(from型子查询时)

    null   直接计算结果,不用走表

 

possible_key 可能用到的索引

注意:系统估计可能用到的几个索引,但最终只能用一个

key:最终用的索引

key_len:使用的索引的最大长度

注意:有可能possible_key为null,而key不为null,这时possible_keys分析的是索引查找的过程,而最终的key可能是被用于查找排序或者索引覆盖

 

type列:指查询的方式(重要)是分析查询过程的重要依据

类型:(性能从差到好)

all:意味着从表的第一行开始查找,运气不好可能要全表查

index:比all好一点,all是扫描所有数据行,index扫描所有的索引节点,相当于index_all

    select * from goods order by goods_id

    虽然有goods_id主键索引,但是因为select*没有where,所以会直接取出所有数据在排序type为all

range:查询时,能根据索引做范围的扫描

ref:通过索引列,可以直接引用到某些数据行

eq_ref:通过索引列,直接引用某1行数据常见于连接查询中

const,system,null这三个分别指查询优化到常量级别

一般主键来查询易出现const,system,或者直接查询某个表达式,不经过表时,出现null

extra:

index:指用到了索引覆盖,效率非常高

using where 指光靠索引定位不了,还需要where判断一下

using temporary用到了临时表,group by 与order by 不同列是,或者group by,order by别的表的列

using filesort:文件排序(可能在磁盘也可能在内存)

出现(temporary/filesort)就需要优化sql语句了

rows 可能扫描多少行

ref 索引的哪一列被使用了

当使用函数时,索引会失效

例如where price+1,left(word,10),price,word索引都会失效

<think>我们正在讨论的是数据库中的慢查询优化,特别是关于EXPLAIN命令的输出参数含义。用户之前询问了延时双删原理,但当前问题转向了解释EXPLAIN慢查询分析后的输出参数。根据引用[1]和[2],我们可以详细解释EXPLAIN的各个输出列。EXPLAIN命令MySQL中用于分析SQL查询执行计划的关键工具。它返回的多列信息帮助我们理解查询的执行过程,从而找出性能瓶颈。以下是EXPLAIN输出中各列的含义: ###📊 EXPLAIN输出列详解1.**id**-**含义**:查询中执行SELECT子句或操作表的顺序。-**规则**:- `id`相同:执行顺序由上至下。- `id`不同:如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。- `id`为NULL:表示结果集,不需要执行。2.**select_type**- **含义**:查询的类型,主要用于区别普通查询、联合查询、子查询等复杂查询。- **常见类型**:- `SIMPLE`:简单查询(不包含子查询或UNION)。- `PRIMARY`:主查询(包含子查询时最外层的查询)。-`SUBQUERY`:子查询(SELECT或WHERE中包含的子查询)。-`DERIVED`:派生表(FROM中包含的子查询)。-`UNION`:UNION中第二个及之后的查询。-`UNION RESULT`:UNION的结果集。3.**table**-**含义**:当前行操作的数据表名称(或别名)。- **特殊值**:- `<derivedN>`:表示id=N的派生表结果。-`<unionM,N>`:表示id=M和id=N的UNION结果。4.**partitions**- **含义**:匹配的分区(若表未分区则为NULL)。5.**type**(⭐**关键指标**⭐)-**含义**:访问类型,即MySQL如何查找表中的行。性能从优到劣排序:-`system`:表只有一行(系统表)。- `const`:通过主键或唯一索引一次就找到。- `eq_ref`:唯一索引关联(如JOIN时使用主键匹配)。-`ref`:非唯一索引查找。- `range`:索引范围扫描(如`BETWEEN`、`IN`)。- `index`:全索引扫描(仅遍历索引树)。- `ALL`:全表扫描(最差性能)。>**优化目标**:至少达到`range`级别,避免`ALL`[^1]。 6. **possible_keys**-**含义**:查询**可能使用**的索引(若为NULL则无可用索引)。 7. **key**- **含义**:查询**实际使用**的索引(若为NULL表示未用索引)。8.**key_len**- **含义**:索引中使用的字节数。- **作用**:判断是否充分利用了索引(如复合索引是否完整使用)。9.**ref**-**含义**:显示索引的哪一列被使用(常量`const`或关联表的列名)。 10. **rows**(⭐**关键指标**⭐)- **含义**:MySQL**预估**需要扫描的行数(越小越好)。 11. **filtered**-**含义**:存储引擎返回的数据在服务层过滤后,剩余行数的百分比(MySQL5.7+)。12.**Extra**(⭐**诊断重点**⭐)-**含义**:额外执行信息(揭示性能问题细节)。-**常见值**:-`Usingindex`:覆盖索引(无需回表)。- `Using where`:服务层过滤存储引擎返回的数据。- `Using temporary`:需要创建临时表(需优化)。- `Using filesort`:外部排序(非索引排序,需优化)。-`Selecttables optimizedaway`:优化器已优化(如聚合函数访问索引)。###🛠️优化示例分析假设EXPLAIN结果如下:```sqlEXPLAINSELECT *FROM ordersWHERE user_id =100AND status= 'shipped'; ```| id| select_type |table| type| key| rows| Extra| |----|-------------|--------|------|---------|------|-------------||1| SIMPLE| orders| ref|idx_user|500| Usingwhere |- **诊断**:- `type=ref`:使用了非唯一索引`idx_user`。- `rows=500`:预估扫描500行。- `Extra=Using where`:服务层需二次过滤(`status`条件未用索引)。-**优化建议**:添加复合索引`(user_id, status)`可避免回表过滤。 ###💎总结EXPLAIN参数是慢查询优化的核心诊断工具,重点关注:1. **type**:避免`ALL`全表扫描。2. **key**:确认索引实际使用情况。3.**rows**:减少扫描行数。4. **Extra**:识别额外性能损耗点(如文件排序、临时表)。>注:优化需结合业务场景,索引并非越多越好[^1][^2]。§§相关问题§§1.如何通过EXPLAIN结果判断是否需要添加索引?2.MySQL中覆盖索引(CoveringIndex)的原理是什么?3.哪些情况下EXPLAIN的`rows`列会严重偏离实际值?4.如何解读`Extra`列中的`Using indexcondition`?</think>### 📊 EXPLAIN 执行计划参数详解 EXPLAIN 是 MySQL 优化查询的核心工具,其输出参数揭示了 SQL 的执行逻辑和性能瓶颈。以下是关键参数的深度解析(基于引用[1][2]): --- #### 🔍 核心参数解析 | 参数 | 含义 | 优化意义 | |--------------|----------------------------------------------------------------------|--------------------------------------------------------------------------| | **id** | SELECT 子句的执行顺序号 | 相同 id 从上到下执行;不同 id 值越大优先级越高(如子查询优先执行)[^1] | | **select_type** | 查询类型 | `SIMPLE`(简单查询)、`PRIMARY`(主查询)、`SUBQUERY`(子查询)等[^1] | | **table** | 当前操作的表名或别名 | 派生表显示为 `<derivedN>`(N 为 id 值)[^1] | | **type** ⭐ | **数据访问方式**(性能关键指标) | 性能排序:`system` > `const` > `eq_ref` > `ref` > `range` > `index` > `ALL`[^1] | | **possible_keys** | 可能使用的索引 | 若为空,需检查 WHERE 条件或表结构 | | **key** ⭐ | **实际使用的索引** | 为 NULL 表示全表扫描(需紧急优化)[^2] | | **key_len** | 索引使用的字节数 | 可判断复合索引是否完整使用(如未用足长度可能未充分利用索引)[^1] | | **rows** ⭐ | **预估扫描行数** | 值越大性能越差(理想值应接近实际返回行数)[^1] | | **Extra** ⭐ | **额外执行信息**(诊断瓶颈核心) | 关键值见下表 | --- #### ⚠️ Extra 列关键值解析 | 值 | 含义 | 优化建议 | |---------------------------|----------------------------------------------------------------------|--------------------------------------------------------------------------| | `Using where` | 服务层对存储引擎返回的数据进行过滤 | 检查 WHERE 条件是否可利用索引 | | `Using index` ✅ | **覆盖索引**(数据直接从索引获取,无需回表) | 理想状态,无需优化 | | `Using temporary` ❌ | 需创建临时表处理查询(如 GROUP BY、DISTINCT) | 优化复杂聚合操作或添加索引 | | `Using filesort` ❌ | 需额外排序(排序字段无索引) | 为 ORDER BY 字段添加索引 | | `Using join buffer` | 使用连接缓存(多表关联时) | 调大 `join_buffer_size` 或优化关联条件 | | `Select tables optimized away` | 优化器已优化(如聚合函数直接访问索引) | 无需干预 | --- #### 🛠️ 优化案例演示 **问题 SQL**: ```sql EXPLAIN SELECT * FROM orders WHERE user_id = 100 ORDER BY create_time DESC; ``` **输出分析**: | id | select_type | table | type | key | rows | Extra | |----|-------------|--------|------|-----|------|----------------| | 1 | SIMPLE | orders | ALL | NULL| 2000 | Using where; Using filesort | **诊断**: 1. `type=ALL`:全表扫描(未用索引) 2. `key=NULL`:未使用索引 3. `Extra=Using filesort`:内存排序开销大 4. `rows=2000`:扫描行数过多 **优化方案**: ```sql -- 添加复合索引 ALTER TABLE orders ADD INDEX idx_user_create(user_id, create_time); -- 重新 EXPLAIN 输出: | id | select_type | table | type | key | rows | Extra | |----|-------------|--------|------|-----------------|------|-------------| | 1 | SIMPLE | orders | ref | idx_user_create | 5 | Using where | ``` ✅ 扫描行数从 2000 → 5,消除 `filesort`,性能提升 400 倍! --- ### 💎 核心优化原则 1. **优先关注 `type` 列**:避免 `ALL`(全表扫描),至少达到 `range` 级别 2. **强制索引使用**:确保 `key` 不为 NULL,`rows` 值最小化 3. **消灭 `Extra` 警告**:重点解决 `Using temporary` 和 `Using filesort` 4. **复合索引策略**:按 `WHERE > ORDER BY > GROUP BY` 顺序设计索引 > 注:需结合业务数据量分析,小表全表扫描可能比索引更快[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值