MySQL Explain 字段分析 2024-04-15 默认分类 暂无评论 1600 次阅读 ## id 每个select对应一个唯一编号, 从1开始自增 - 序号相同 从上往下执行 - 序号不同 由大到小 - 两种混合, 先执行序号大的 同级从上往下执行 - 如果显示NULL 最后执行, 表示结果集 不需要使用它来执行 select_type `select_type`:表示 `select` 查询的类型, 主要是用于区分各种复杂的查询, 例如:`普通查询`、`联合查询`、`子查询`等。 | 类型 | 含义 | | :------------------- | :--------------------------------------- | | SIMPLE | 简单SELECT,不使用UNION或子查询等 | | PRIMARY | 查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY | | UNION | UNION中的第二个或后面的SELECT语句 | | DEPENDENT UNION | UNION中的第二个或后面的SELECT语句,取决于外面的查询 | | UNION RESULT | UNION的结果 | | SUBQUERY | 子查询中的第一个SELECT (结果不依赖于外部查询) | | DEPENDENT SUBQUERY | 子查询中的第一个SELECT,取决于外面 的查询 | | DERIVED | 派生表的SELECT, FROM子句的子查询 | | UNCACHEABLE SUBQUERY | 一个子查询的结果不能被缓存,必须重新评估外链接的第一行 | type | 类型 | 含义 | | | --------------- | ---------------------------------- | ---------- | | const | 一条记录(等值查询) | | | system | 表只存在一行记录 | | | | | | | eq_ref | 关联查询, 条件唯一索引或者主键 | 性能仅次于const | | ref | 非主键索引的单值查询 | | | ref_or_null | 在ref基础上,增加null值查询 全表扫描 | | | index_merge | 多个结果合并 统一回表查询 同时对结果排序 | | | | | | | unique_subquery | 优化器会对语句进行优化 基本用不到 | | | index_subquery | | | | | 效率较低 尽量少用 | | | range | 索引树范围扫描 (Between, like, in, >, <等) | | | index | 只需要查询索引树 | 两种都是全表扫描 | | all | 需要全表扫描 | | key_len `key_len`:表示查询用到的索引长度(字节数),原则上长度越短越好 。 - 单列索引,那么需要将整个索引长度算进去; - 多列索引,不是所有列都能用到,需要计算查询中实际用到的列。 > 注意:`key_len`只计算`where`条件中用到的索引长度,而排序和分组即便是用到了索引,也不会计算到`key_len`中。 possible_keys `possible_keys`:表示在`MySQL`中通过哪些索引,能让我们在表中找到想要的记录, 一旦查询涉及到的某个字段上存在索引,则索引将被列出, **但这个索引并不定一会是最终查询数据时所被用到的索引**。具体请参考上边的例子。 key `key`:区别于`possible_keys`,key是查询中实际使用到的索引, 若没有使用索引,显示为`NULL`。具体请参考上边的例子。 > 当 `type` 为 `index_merge` 时,可能会显示多个索引。 ref 常见的有:`const`,`func`,`null`,字段名。 - 当使用常量等值查询,显示`const`, - 当关联查询时,会显示相应关联表的`关联字段` - 如果查询条件使用了`表达式`、`函数`,或者条件列发生内部隐式转换,可能显示为`func` - 其他情况`null` **rows** `rows`:以表的统计信息和索引使用情况, 估算要找到我们所需的记录,需要读取的行数。 这是评估`SQL` 性能的一个比较重要的数据, `mysql`需要扫描的行数,很直观的显示 `SQL` 性能的好坏, 一般情况下 `rows` 值越小越好。 **filtered** `filtered` 这个是一个百分比的值,表里符合条件的记录数的百分比。 简单点说,这个字段表示存储引擎返回的数据在经过过滤后,剩下满足条件的记录数量的比例。 在`MySQL.5.7`版本以前想要显示`filtered`需要使用`explain extended`命令。 `MySQL.5.7`后,默认`explain`直接显示`partitions`和`filtered`的信息。 **Extra** `Extra` :不适合在其他列中显示的信息,`Explain` 中的很多额外的信息会在 `Extra` 字段显示。 1、Using index `Using index`:我们在相应的 `select` 操作中使用了覆盖索引, 通俗一点讲就是查询的列被索引覆盖,使用到覆盖索引查询速度会非常快,`SQl`优化中理想的状态。 > 什么又是覆盖索引? 简单来说就是通过索引即可查出全部字段不需要回主索引查找出其他字段 一条 `SQL`只需要通过索引就可以返回,我们所需要查询的数据(一个或几个字段), 而不必通过二级索引,查到主键之后再通过主键查询整行数据(`select *` )。 2、Using where `Using where`:查询时未找到可用的索引,进而通过`where`条件过滤获取所需数据, 但要注意的是并不是所有带`where`语句的查询都会显示`Using where`。 下边示例`create_time` 并未用到索引,`type` 为 `ALL`,即`MySQL`通过全表扫描后再按`where`条件筛选数据。 ```Bash mysql> EXPLAIN SELECT one_name from one where create_time ='2020-05-18'; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | one | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ ``` 3、Using temporary `Using temporary`:表示查询后结果需要使用临时表来存储,一般在排序或者分组查询时用到。 4、Using filesort `Using filesort`:表示无法利用索引完成的排序操作,也就是`ORDER BY`的字段没有索引,通常这样的SQL都是需要优化的。 5、Using join buffer `Using join buffer`:在我们联表查询的时候,如果表的连接条件没有用到索引,需要有一个连接缓冲区来存储中间结果。 先看一下有索引的情况:连接条件 `one_name` 、`two_name` 都用到索引。 接下来删掉 连接条件 `one_name` 、`two_name` 的字段索引。 发现`Extra` 列变成 `Using join buffer`,`type`均为全表扫描,这也是`SQL`优化中需要注意的地方。 6、Impossible where `Impossible where`:表示在我们用不太正确的`where`语句,导致没有符合条件的行。 > 示例: `SELECT one_name from one WHERE 1=2; ` 7、No tables used `No tables used`:我们的查询语句中没有`FROM`子句,或者有 `FROM DUAL`子句。 ```Bash mysql> EXPLAIN select now(); +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ ``` `Extra`列的信息非常非常多,这里就不再一一列举了, 详见 `MySQL`官方文档 :`https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#jointype_index_merge` 总结 在 MySQL 中,EXPLAIN 输出包含了一系列字段,其中最重要的字段通常是以下几个: 1. **table:** 这是查询涉及的表的名称。在连接查询中,可能会有多个表。 2. **type:** 这表示了查询的访问类型,它显示了 MySQL 在表中找到所需行的方式。常见的访问类型包括 "const"、"eq_ref"、"ref"、"range"、"index" 和 "ALL" 等。 3. **possible_keys:** 这是可能用于此查询的索引的列表。它显示了在查询中使用的索引。 4. **key:** 这是 MySQL 实际选择的索引。如果该字段显示为 NULL,则表示 MySQL 没有选择索引,并且需要检查查询以确定是否可以优化。 5. **rows:** 这是 MySQL 估计必须检查以返回请求的数据的行数。 6. **Extra:** 这个字段包含了其他有关查询执行的信息,比如是否使用了临时表、文件排序等。 这些字段中的信息可以帮助你评估查询的性能,并确定是否需要优化查询或表结构。 参考 > [Hollis: 面试官:不会看 Explain执行计划,简历敢写 SQL 优化?](https://mp.weixin.qq.com/s/OpS_F5lG9CaFw4xqnofWLw) > [全套MySQL Explain教程视频,1小时掌握mysql中explain执行计划的使用精髓](https://www.bilibili.com/video/BV1Wu41147q9/?spm_id_from=333.337.search-card.all.click&vd_source=f1a7951aa84af4793b91a3e046fcd901) 文章目录 select_type type key_len possible_keys key ref **rows** **filtered** **Extra** 1、Using index 2、Using where 3、Using temporary 4、Using filesort 5、Using join buffer 6、Impossible where 7、No tables used 总结 参考 标签: mysql 转载请注明文章来源 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭