MySQL 执行计划说明

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 执行计划说明相关的知识,希望对你有一定的参考价值。

上一篇文章“SQL关联查询 直接join 和子查询的区别”中提到了explain,即执行计划。执行计划是数据库引擎的重要一环,今天针对explain结果了解下,顺便提及几个有意思的话题,如“回表”、“如何在mysql中实现rowNum”。

explain结果说明

技术分享图片

  • select_type
类型 说明
SIMPLE 简单SELECT(不使用UNION或子查询等)
PRIMARY 主查询,即最外面的SELECT
UNION UNION中的第二个或后面的SELECT语句
DEPENDENT UNION NION中的第二个或后面的SELECT语句,取决于外面的查询
UNION RESULT UNION的结果
SUBQUERY 子查询中的第一个SELECT
DEPENDENT SUBQUERY 子查询中的第一个SELECT,取决于外面的查询
SUBQUERY 导出表的SELECT(FROM子句的子查询)
  • table
    输出结果集的表名

  • partitions
    存在分区时,使用到哪些分区

  • type
    连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。常见访问类型如下,按照性能排序,从上到下,从差到好。一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。
类型 示例说明
ALL 全表扫描 一般是没有where条件或者where条件没有使用索引的查询语句
index 索引全扫描 一般是查询的字段都有索引的查询语句
range 索引范围扫描 常用于<、<=、>、>=、between等操作
ref 非唯一索引扫描 使用非唯一索引或唯一索引的前缀扫描,返回匹配某个单独值的记录行
eq_ref 唯一索引扫描 类似ref,区别在于使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配
const,system 单表最多有一个匹配行 onst/system出现在根据主键primary key或者 唯一索引 unique index 进行的查询
NULL 不用扫描表或索引 select 1 from dual
  • possible_keys
    列指出MySQL能使用哪个索引在该表中找到行

  • key
    显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL

  • key_len
    显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

  • ref
    显示使用哪个列或常数与key一起从表中选择行。

  • rows
    显示MySQL认为它执行查询时必须检查的行数。

  • filtered
    存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例(百分比)

  • extra
    包含MySQL解决查询的详细信息,也是关键参考项之一。
extra元素 说明
Distinct 一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
Not exists MYSQL 优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
Range checked for each
Record 没有找到理想的索引,因此对于从前面表中来的每一 个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
Using filesort 表示MySQL需额外排序操作, 不能通过索引顺序达到排序效果
Using index 表示索引覆盖,不会回表查询
Using temporary 通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
Using where 表示进行了回表查询

什么是回表

简单来说就是数据库根据索引找到了指定的记录所在行后,还需要根据rowid再次到数据块里取数据的操作。比如这样的执行计划,先索引扫描,再通过rowid去取索引中未能提供的数据,即为回表。“回表”一般就是指执行计划里显示的“TABLE ACCESS BY INDEX ROWID”。再例如,虽然只查询索引里的列,但是需要回表过滤掉其他行。

怎么避免回表?
将需要的字段放在索引中去。查询的时候就能避免回表。但是不要刻意去避免回表,那样代价太了。也不是将所有的字段都放在所有中。

回表和MySQL的索引实现有关系,有兴趣的朋友可以进一步了解B+树相关原理,参照下面这篇文章“从B树、B+树、B*树谈到R 树”。

MySQL如何获取rownum

不同于oracle的rownum,mysql不太直接提供这样的字段,但是可以用变量的方法添加伪自增序列,语法格式为
SELECT @rownum:[email protected]+1 AS rownum, table_name.* FROM (SELECT @rownum:=0) r, table_name ;

以上是关于MySQL 执行计划说明的主要内容,如果未能解决你的问题,请参考以下文章

MySql查询优化-执行计划explain详细说明

MySQL_执行计划详细说明

MySQL执行计划分析

mysql explain执行计划分析

MySQL 查看执行计划

MySQL执行计划分析