MySQL——explain

什么是MySQL执行计划

要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有简单的了解。

MySQL本身的功能架构分为三个部分,分别是 应用层、逻辑层、物理层,不只是MySQL ,其他大多数数据库产品都是按这种架构来进行划分的。

  • 应用层: 主要负责与客户端进行交互,建立链接,记住链接状态,返回数据,响应请求,这一层是和客户端打交道的。
  • 逻辑层: 主要负责查询处理、事务管理等其他数据库功能处理,以查询为例。

首先接收到查询SQL之后,数据库会立即分配一个线程对其进行处理,第一步查询处理器会对SQL查询进行优化,优化后会生成执行计划,然后交由计划执行器来执行。

计划执行器需要访问更底层的事务管理器,存储管理器来操作数据,他们各自的分工各有不同,最终通过调用物理层的文件获取到查询结构信息,将最终结果响应给应用层。

  • 物理层: 实际物理磁盘上存储的文件,主要有分文数据文件,日志文件。

通过上面的描述,生成执行计划是执行一条SQL必不可少的步骤,一条SQL性能的好坏,可以通过查看执行计划很直观的看出来,执行计划提供了各种查询类型与级别,方便我们进行查看以及为作为性能分析的依据。

如何分析执行计划

MySQL为我们提供了 explain 关键字来直观的查看一条SQL的执行计划。

explain显示了MySQL如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。

先解析一条sql语句,看出现什么内容。

EXPLAIN SELECT s.uid,s.username,s.name,f.email,f.mobile,f.phone,f.postalcode,f.address
FROM uchome_space AS s,uchome_spacefield AS f
WHERE 1 
AND s.groupid=0
AND s.uid=f.uid

在这里插入图片描述

id

SELECT识别符。这是SELECT查询序列号。这个不重要,查询序号即为sql语句执行的顺序,看下面这条sql:

EXPLAIN SELECT *FROM (SELECT* FROMuchome_space LIMIT 10)AS s

它的执行结果为
在这里插入图片描述
可以看到这时的id变化了。

select_type

select类型,它有以下几种值:
1、simple:它表示简单的select,没有union和子查询。
2、primary:最外面的select,在有子查询的语句中,最外面的select查询就是primary,上图中就是这样。
3、union:union语句的第二个或者说是后面那一个.现执行一条语句:

explain  select  *  from uchome_space limit 10 union select * from uchome_space limit 10,10

会有如下结果:
在这里插入图片描述
第二条语句使用了union

4、dependent union:UNION中的第二个或后面的SELECT语句,取决于外面的查询。
5、 union result:UNION的结果,如上面所示。

还有几个参数,这里就不说了,不重要。

table

输出的行所用的表,这个参数显而易见,容易理解。

partitions

如果查询是基于分区表的话,显示查询将访问的分区。

type(重要且困难)

连接类型。有多个参数,先从最佳类型到最差类型介绍 :

1、system:表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计。
2、const:表最多有一个匹配行,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快。记住一定是用到primary key 或者unique,并且只检索出一条数据的 情况下才会是const,看下面这条语句:

explain SELECT * FROM `asj_admin_log` limit 1

在这里插入图片描述
虽然只搜索一条数据,但是因为没有用到指定的索引,所以不会使用const。继续看下面这个。

explain SELECT * FROM `asj_admin_log` where log_id = 111

在这里插入图片描述
log_id是主键,所以使用了const。所以说可以理解为const是最优化的。

3、eq_ref:对于eq_ref的解释,mysql手册是这样说的:“对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY”。eq_ref可以用于使用=比较带索引的列。看下面的语句:

explain select * from uchome_spacefield,uchome_space where uchome_spacefield.uid = uchome_space.uid

得到的结果是下图所示。很明显,mysql使用eq_ref联接来处理uchome_space表。
在这里插入图片描述
4、ref: 对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话,使用普通索引就是这种类型),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。看下面这条语句:

explain select * from uchome_space where uchome_space.friendnum = 0

得到结果如下,这条语句能搜出1w条数据。
在这里插入图片描述
5、ref_or_null:该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。
上面这五种情况都是很理想的索引使用情况。

6、index_merge:该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

索引合并优化: 索引合并是把几个索引的范围扫描合并成一个索引。索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。这些需要合并的索引只能是一个表的。不能对多表进行索引合并。简单的说, 索引合并,让一条sql可以使用多个索引。对这些索引取交集,并集,或者先取交集再取并集。从而减少从数据表中取数据的次数,提高查询效率。
例如:
在这里插入图片描述
7、unique_subquery :用于where中的in形式子查询,子查询返回不重复值唯一值。
8、index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重;
9、range:给定范围内的检索,使用一个索引来检查行。看下面两条语句:

explain select * from uchome_space where uid in (1,2)
explain select * from uchome_space where groupid in (1,2)

uid有索引,groupid没有索引,结果是第一条语句的联接类型是range,只检索给定范围的行,使用一个索引来选择行。
10、index: 该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。
11、all:对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。

思考:为什么唯一索引和主键比较快呢,因为当查找到唯一索引或主键对应的值就可以返回结果停止查找了,而普通索引还要继续查找。

possible_keys

指出MySQL能使用哪个索引在该表中找到行

key

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

key_len

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

ref

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

rows

显示MySQL认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数。

filtered

显示了通过条件过滤出的行数的百分比估计值。

Extra

该列包含MySQL解决查询的详细信息

  • Distinct:MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
  • Select tables optimized away:MySQL根本没有遍历表或索引就返回数据了,表示已经优化到不能再优化了。
  • Not exists:MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
  • range checked for each record (index map: #):MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
  • Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行,说明查询就需要优化了。
  • Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
  • Using temporary:为了解决查询,MySQL需要创建一个临时表来容纳结果,说明查询就需要优化了。
  • Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。
  • Using sort_union(…), Using union(…), Using intersect(…):这些函数说明如何为index_merge联接类型合并索引扫描。
  • Using index for group-by:类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值