执行计划mysql
模拟优化器执行SQL查询语句,从而知道数据库如何处理SQL,分析查询语句或表结构的性能瓶颈。
mysql---explain
explain + sql
执行结果字段解释:
ID
相同,执行顺序由上至下
执行顺序是t1,t3,t2,select_type提示都是简单查询
------------------------------------------------------------------------------------------------
如果是嵌套子查询,id会递增,id越大越先执行
这个很好理解,括号里的子查询先被执行,select_type字段也标识出来哪些是子查询。
---------------------------------------------------------------------------------------
既有相同又有不同,id越大越先执行,相同的顺序执行
这里S1是衍生表,所以table部分是derived2,derived是衍生的意思,2指的是由哪个ID衍生出来。
-----------------------------------------------------------------------------------------------
select_type
查询类型
simple:简单查询,不包括子查询,union等;
primary:查询中若包含任何复杂的子查询,最外层被标记为这个类型,就是最后被加载的那个,但是多表查询时可能有多个primary;
subquery:子查询部分;
derived:在from列表中包含的子查询被标记为derived(衍生);
union:若第二个select出现在union之后,则被标记为union,
若union包含在from子句的子查询中,则外层select将被标记为derived;
union result:union后的结果集。
table
数据来自哪张表
type
访问类型排序,从好到差依次是
system>const>eq_ref>ref>range>index>All
system:表只有一条记录,这是const类型的特例,平时不会出现,可以忽略不计;
const:表示通过索引一次就找到了,用于比较主键或唯一索引,因为只匹配一行数据,所以很快,如果将主键置于where条件中,就会是const类型;
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配;
ref:非唯一性索引扫描,对于每个索引键,表中有多条记录与之匹配,假设部门id是索引,查这个部门id对应的员工,有多条数据;
range:通过一个索引来检索一个范围内的记录,假设订单创建时间是索引,查询最近一个月内的订单,例如>,<,between,in;
index:查询的结果就是索引的值,及遍历的是索引树而不是表,例如查询表的所有主键;
All:遍历全表,但是ALL也不代表一定要优化,假如某个表数据量少,字段也少,我就需要全查出来,分页都不用,那就完全不需要优化。
possible_keys
显示可能应用在这个表中的索引,一个或多个,但不一定被查询使用。
key
实际使用的索引;
查询中若使用了覆盖索引,则该索引仅出现在key列表中。
覆盖索引:指的是要查询的内容,都在索引上,刚好被索引覆盖,也就是只需要查询索引,不需要查询表了,通常就是联合索引比较容易实现覆盖索引。
key_len
表示索引中使用的字节数,说白了就是查询条件里索引用的越多,len越长,但是这一点需要和查询结果的精度同时考虑,取平衡。
ref
type 是 ref 时,显示索引的哪一列被使用了,如果可能的话,是一个常数。
row
查询到符合条件的结果为止,每张表有多少数据被查询过。
extra
不适合显示在以上字段里的重要内容
比较重要的信息有
Using filesort :说明会对数据使用一个外部的索引排序,而不是按照表设计的索引,即“文件排序”,这个要尽量避免,通常来说就是你的排序字段不在索引中;
另外还有一种情况,一个复合索引a1_a2_a3,通过a1作为条件查询出a1,a3,然后按a3排序,这种情况虽然a1,a3都在复合索引a1_a2_a3中,但是没有a2,所以出现文件排序,解决方案就是,将a2加入到排序/查询结果中去,这样虽然看上去sql复杂了一些,但其实性能更好;
Using temporary:使用了临时表保存中间结果,指数据库自己创建了临时表用于排序/分组,使用完后删除,常见于排序order by和分组group by,这个要绝对避免。
举个例子,有复合索引a1_a2_a3,然后查询语句分组group by a2,这时就会出现这个提示,因为数据库需要对a1的分组情况做临时表,所以这种情况下,直接group by a1,a2性能更好,说白了就是,如果要分组,分组条件最好是索引。
需要注意的是,group by a1/a1,a2/a1,a2,a3都可以,但是group bu a1,a3/a2,a3不行,依然会报这个问题,因为复合索引内的字段是有顺序的,不能跳过。
Using Index:表示使用了覆盖索引,避免了查询表,效率很好;
Using Where:表面where条件里用了索引;