mysql explain 详解
在进行mysql语句分析或优化时,通常都会用到explain 语句,通过explain语句可以知道mysql的查询逻辑和是否使用索引或者索引是否生效等信息。
语法格式:explain mysql语句
如:explain select * from account a right join account_order ao on a.id=ao.user_id where ao.user_id="0001";
字段说明:
id:select 标识符,这是mysql语句的执行顺序。
select_type: select的查询类型,分别为:
- SIMPLE 检查select查询(不使用union或子查询)
- PRIMARY 最外面的select 查询
- UNION union中的第二个或后面的select语句
- DEPENDENT UNION union中的第二个或后面的select语句,取决于外面的查询
- UNION RESULT 从union临时表检索结果的select
- SUBQUERY 子查询中的第一个select
- DEPENDENT SUBQUERY 子查询中的第一个select,取决于外面的查询
- DERIVED 导出表的select(from子句的子查询)
table: 该查询语句所对应的表名
type:联接类型或访问类型,分别为:
- system 表仅有一行(=系统表)。这是const联接类型的一个特例。
- const 表中最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!比如匹配主键索引或唯一索引时,当前匹配到1条记录时,就停止之后的查询。因此速度比较快。
- eq_ref 在多表查询时,对于前、后表匹配时,后面的表仅匹配到1条记录即结束之后的匹配。类似于const类型,因此,可以理解为在多表联合查询时,通过unique唯一索引或primary key主键索引进行关联,和作为where的查询条件,当前查询到一条记录后,就返回查询结果并结束之后的匹配,因此在组合查询时,也是查询速度相对较好的。
- ref 普通索引查询,也就是查询条件不是主键索引或唯一索引,匹配的结果可能是一条或多条记录,ref的查询条件可以为索引字段=或<=>的操作符。
- ref_or_null 与ref类似,也是索引查询,但是可以专门搜索包含null值的行,如where 索引字段=value or 索引字段 is null。
- index_merge 表示使用了索引合并优化方法,索引合并方法用于通过range扫描搜索行将结果合成一个。合并会产生并集、交集或者正在进行的扫描的交集的并集。
- unique_subquery 该类型表示使用了in 包含子查询且子查询根据主键索引或唯一索引进行查询,如value in (select primary_key from table_name where some_expr)
- index_subquery 与unique_subquery类似,但是子查询中引用的是非唯一索引。
- range 表示根据索引查询某个条件范围,可以使用=、<>、>、>=、<、<=、is null、<=>、between 或in 操作符来查询。
- index 只匹配索引树,通常比all类型快,因为索引文件通常比数据文件小,当查询只使用作为单索引一部分的列时,mysql可以使用该类型。
- all 全表匹配,没有根据索引进行匹配,当表的数据量很大时,查询速度会很慢。
根据type类型效率按优排序为:system>const>eq_ref>ref>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>all
possible_keys:表示mysql能使用哪个索引进行查询,如果为null,则说明没有相关索引。可以通过alter table 语法去建相应的索引。
key:表示mysql实际决定使用的索引,如果为null,说明该查询没有使用索引,比如当前已使用索引进行条件过滤,但是索引失效,则key的值会为null。
key_len:该列显示mysql决定使用的键长度。如果键是null,则长度为null,注意通过key_len值我们可以确定mysql将实际使用一个多部关键字的几个部分。
ref:显示使用哪个列或常数与key一起从表中进行匹配。
rows:显示msql认为它执行查询时必须检查的行数。
Extra:该列包含mysql解决查询的详细信息。对应的内容分别为:
- Distinct 表示mysql在发现第1个匹配行后,停止为当前的行组合匹配更多的行。
- Not exists 表示mysql能够对查询进行left join优化,发现1个匹配left join 标准的行后,不再为前面的行组合在该表内检查更多的行。
- range checked for each record(index map:#) 表示mysql没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。对前面的表的每个行组合,mysql检查是否可以使用range或index merge访问方法来匹配行。
- using filesort 表示mysql需要额外的一次传递,以找出如何按排序顺序检索行。通过联接类型浏览所有行并为所匹配where子句的行保保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行。
- using index 表示从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。当查询只使用作为单一索引部分的列时,可以使用该策略。
- using temporary 表示为了解决查询,mysql需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的group by 或order by 子句时。
- using where 表示where子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果extra值不为using where 并且表联接类型为all或index ,查询可能会有一些错误。如果想要使查询尽可能快,应找出using filesort 和using temporary 的extra值。
- using sort_union(),using unoin() ,using intersect() 这些函数说明如何为index merge联接类型合并索引扫描。
- using index for group-by 类似于访问表的using index 方式,using index for group-by 表示mysql发现了一个索引,可以用来查询group by 或distinct查询的所有列,而不要额外搜索硬盘访问实际的表。并且,按最有效的方式使用索引,以便对于每个组,只读取少量索引条目。