MySQL EXPLAIN 完全解读

MySQL EXPLAIN 完全解读

一、一个EXPLAIN简单执行

二、简单了解

在MySQL中,EXPLAIN语句用于获取关于如何执行SQL语句的信息。以下是EXPLAIN输出的各个列的含义:

2.1. id:查询的标识符。

如果一个查询包含子查询,那么每个子查询都会有一个不同的id。

2.2. select_type:查询的类型。

这个列的值可以是SIMPLE(简单查询,不包含子查询或者UNION)、PRIMARY(查询中最外层的查询)、SUBQUERY(子查询中的第一个SELECT)、DERIVED(派生表的查询,MySQL会先执行这个查询,然后把结果放在临时表中)等。

2.3. table:输出结果集的表。

2.4. type:连接类型,这是MySQL决定如何查找表中行的方法。

常见的值有const、eq_ref、ref、range、index和ALL。

2.5. possible_keys:可能用到的索引。

2.6. key:实际使用的索引。

2.7. key_len:使用的索引的长度。

在不损失精度的情况下,长度越短越好。

2.8. ref:显示索引的哪一部分被使用了

如果可能的话,会显示哪个列或常数被用于查找索引列。

2.9. rows:MySQL认为必须检查的用来获取查询结果的行数。

2.10. Extra:包含MySQL解决查询的详细信息。

常见的值有Using index(表示MySQL只用到了索引,没有去读取实际的行,Using where(表示MySQL使用了WHERE过滤器)等。

三、重点讲解

3.1、SELECT_TYPE列表示MySQL如何查找表中的行。

SELECT_TYPE 是 MySQL 中 EXPLAIN 命令的输出列之一,用于描述查询中每个 SELECT 子句的类型。以下是一些可能的 SELECT_TYPE 值及其含义:

  1. SIMPLE:简单 SELECT(不使用 UNION 或子查询等)。
sql 复制代码
SELECT * FROM table1;
  1. PRIMARY:查询中如果包含任何复杂的子部分,最外层的 SELECT 被标记为 PRIMARY。
sql 复制代码
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
  1. SUBQUERY:在 SELECT 或 WHERE 列表中的第一个 SELECT 子查询。
sql 复制代码
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
  1. DERIVED:在 FROM 列表中的子查询。
sql 复制代码
SELECT * FROM (SELECT id FROM table2) AS derived_table;
  1. UNION:如果第二个或后续的 SELECT 是 UNION 的一部分,则 SELECT_TYPE 是 UNION。
sql 复制代码
SELECT column1 FROM table1 UNION SELECT column2 FROM table2;
  1. UNION RESULT:从 UNION 表中选择结果的 SELECT。
sql 复制代码
(SELECT column1 FROM table1 UNION SELECT column2 FROM table2) ORDER BY 1;

3.2、type列表示MySQL如何查找表中的行。

3.2.1、一些常见的值及其含义

  1. const:这是最好的一种连接类型,表示MySQL能够在索引中一次就找到相关的行。这通常发生在你执行主键或唯一索引的查询,并且只返回一行结果的情况下。
  2. eq_ref:这是第二好的连接类型,表示MySQL在连接表时,对于每一行都只需要读取一次,这通常发生在你使用主键或唯一索引的情况下。
  3. ref:这种连接类型表示MySQL需要对每个外键组合执行一次查找,这通常发生在你使用非唯一索引或者非主键的情况下。
  4. range:这种连接类型表示MySQL在索引中进行范围查找,这通常发生在你使用BETWEEN、<、>、IS NULL或者IN等操作符的情况下。
  5. index:这种连接类型表示MySQL进行全索引扫描,这通常发生在你的查询只需要从索引中获取数据,而不需要查看实际的行数据的情况下。
  6. ALL:这是最差的连接类型,表示MySQL需要进行全表扫描,这通常发生在你的查询没有使用到索引的情况下。

3.2.2、一些例子

假设我们有一个名为users的表,其中包含id(主键)、name和email(唯一索引)三个字段。

  1. 如果我们执行查询SELECT * FROM users WHERE id = 1,那么type列的值就是const,因为MySQL可以通过主键一次就找到相关的行。
  2. 如果我们执行查询SELECT * FROM users WHERE email = 'example@example.com',那么type列的值就是ref,因为MySQL需要对每个外键组合执行一次查找。
  3. 如果我们执行查询SELECT * FROM users WHERE id BETWEEN 1 AND 1000,那么type列的值就是range,因为MySQL在索引中进行范围查找。
  4. 如果我们执行查询SELECT id FROM users ORDER BY id,那么type列的值就是index,因为MySQL进行全索引扫描。
  5. 如果我们执行查询SELECT * FROM users,那么type列的值就是ALL,因为MySQL需要进行全表扫描。

3.3、EXPLAIN命令的key列用于显示MySQL在查询中使用的键(索引)

3.3.1、NULL:MySQL 没有使用任何键(索引)进行查询。

sql 复制代码
EXPLAIN SELECT * FROM table1 WHERE non_indexed_column = 'value';

在这个例子中,non_indexed_column 是一个没有索引的列,所以 key 的值为 NULL。

3.3.2、索引名称:如果 MySQL 使用了某个索引进行查询,那么 key 的值就是那个索引的名称。

sql 复制代码
EXPLAIN SELECT * FROM table1 WHERE indexed_column = 'value';

在这个例子中,indexed_column 是一个有索引的列,所以 key 的值就是该列的索引名称。

3.3.3、PRIMARY:如果 MySQL 使用了主键索引进行查询,那么 key 的值就是 PRIMARY。

sql 复制代码
EXPLAIN SELECT * FROM table1 WHERE id = 1;

3.4、key_len列在MySQL的EXPLAIN输出中表示的是MySQL在索引中使用的字节数

这个值是根据索引类型和索引字段的类型以及长度计算出来的。

例如,对于一个CHAR(10)类型的字段,如果它是一个字符串类型的索引,那么key_len的值就是10。如果这个字段是一个整数类型的索引,那么key_len的值就是4(因为整数类型的索引的长度是4字节)。 需要注意的是,key_len并不一定等于索引字段的实际长度。例如,对于一个VARCHAR(100)类型的字段,即使它的最大长度是100,但如果在查询中只使用了前10个字符,那么key_len的值就是10。 总的来说,key_len可以帮助你理解MySQL如何使用索引,以及索引的效率。在不损失精度的情况下,key_len的值越小,表示使用的索引越精简,查询效率可能会更高。

3.5、ref 列显示了MySQL如何使用索引来查找数据

例如,假设我们有一个名为 users 的表,其主键为 id,并且有一个名为 email 的唯一索引。以下是一些可能的情况:

  1. 使用主键进行查询:
sql 复制代码
EXPLAIN SELECT * FROM users WHERE id = 1;

在这个例子中,EXPLAIN 的输出可能会显示 ref 列的值为 const,表示我们使用了一个常量值(在这种情况下是 1)来查找主键索引。

  1. 使用唯一索引进行查询:
sql 复制代码
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';

在这个例子中,EXPLAIN 的输出可能会显示 ref 列的值为 const,表示我们使用了一个常量值(在这种情况下是 'user@example.com')来查找 email 索引。

  1. 使用非唯一索引进行查询:

假设 users 表有一个非唯一索引 status,我们可以执行以下查询:

sql 复制代码
EXPLAIN SELECT * FROM users WHERE status = 'active';

在这个例子中,EXPLAIN 的输出可能会显示 ref 列的值为 const,表示我们使用了一个常量值(在这种情况下是 'active')来查找 status 索引。

请注意,ref 列的值并不总是 const。如果我们使用了一个列的值来查找索引,那么 ref 列的值就会是那个列的名称。例如,如果我们有一个查询 SELECT * FROM users u JOIN orders o ON u.id = o.user_id,那么 EXPLAIN 的输出可能会显示 ref 列的值为 o.user_id,表示我们使用了 orders 表的 user_id 列的值来查找 users 表的主键索引。

3.6、Extra列提供了关于查询执行方式的额外信息

以下是一些可能出现在Extra列中的值及其含义:

1.Using index :这表示MySQL只需要读取索引,而不需要读取数据行。这通常发生在所有需要的数据列 都包含在索引中的情况下。

2.Using where :这表示MySQL服务器将在存储引擎检索行后再进行过滤。这可能意味着存储引擎无法执行全部的过滤工作,可能是因为查询的某部分没有被索引覆盖。

3.Using temporary :这表示MySQL需要创建一个临时表来存储结果,这通常发生在对不同的列进行ORDER BY和GROUP BY的情况下。

4.Using filesort :这表示MySQL会对结果使用一个外部索引排序,而不是按照表中的索引顺序进行读取。这通常发生在ORDER BY或GROUP BY的列不是索引的一部分的情况下。

5.Range checked for each record (index map: N) :这表示MySQL无法确定使用哪个索引,所以对于每一行数据,它都会检查是否可以使用索引。

6.Impossible WHERE noticed after reading const tables:这表示WHERE子句的条件总是false,当检查到这一点时,查询已经不再继续。

相关推荐
Dovir多多23 分钟前
渗透测试入门学习——php与mysql数据库连接、使用session完成简单的用户注册、登录
前端·数据库·后端·mysql·安全·html·php
计算机学姐32 分钟前
基于微信小程序的食堂点餐预约管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
二十雨辰37 分钟前
[苍穹外卖]-09Spring Task定时任务
java·数据库·spring
科研小白_d.s38 分钟前
数据库课程设计mysql
数据库·mysql·课程设计
code.song39 分钟前
校园社团|基于springBoot的校园社团信息管理系统设计与实现(附项目源码+论文+数据库)
数据库·spring boot·后端
code.song1 小时前
医疗报销|基于springBoot的医疗报销系统设计与实现(附项目源码+论文+数据库)
数据库·spring boot·后端
A懿轩A1 小时前
MySQL SQL多表查询语句各种连接
java·开发语言·数据库·sql·mysql·mybatis
网安詹姆斯1 小时前
网络安全(黑客技术)2024年三个月自学计划
网络·数据结构·python·mysql·安全·web安全·github
代码代码快快显灵1 小时前
XML标记语言
xml·java·数据库
源代码:趴菜2 小时前
MySQL函数:数值函数
数据库·mysql