MySql 执行计划
mysql执行计划是sql语句经过查询优化器后,查询优化器会根据用户的sql语句所包含的字段和内容数量等统计信息,选择出一个执行效率最优(mysql系统认为最优)的执行计划,然后根据执行计划,调用存储引擎提供的接口,获取数据。
但是,在mysql执行的时候,到底使用了一个什么样的执行计划,有没有用到索引。当数据规模比较大的时候,sql执行的时候,执行计划不同,会直接影响sql的执行速度。这个时候,就需要对sql语句执行进行调试。
mysql我们在调试sql语句的时候,不会像我们写java或者其他语言代码那样通过打断点的方式进行代码调试。这个时候,我们就需要通过查看执行计划来调试我们的sql了。Mysql通过EXPLAIN来查看执行计划,我们写sql语句的时候,在语句之前加一个EXPLAIN就可以了。EXPLAIN可以用在SELECT、DELETE、INSERT、PEPLACE以及UPDATE等语句中,如:
1 EXPLAIN SELECT 2 * 3 FROM 4 school 5 WHERE 6 school_nick = '县第一小学'
执行后,结果如下:
这里介绍下每个字段以及每个字段的含义:
id
id是执行计划的标识符,是SELECT 查询的序号。如果结果集会跟其他表的结果用UNION关键字相结合,那么id可能为空。
id是否为空,对执行计划的影响不大,如果有兴趣可以看另外一篇博客:mysql执行计划id为空—UNION关键字,这里不再赘述。
select_type
select_type表示sql语句查询的类型。具体表示如下表:
select_type的值 | 含义 |
SIMPLE | 简单的select查询,没有使用关联和子查询。 |
PRIMARY | 最外层select,包含子查询的时候,最外层的查询 |
UNION | 在一个UNION查询中,第二次或以后的子查询操作 |
DEPENDENT UNION | 在一个UNION查询中,第二次子查询或以后的SELECT查询的时候需要依赖外部的查询 |
UNION RESULT | UNION的返回结果集 |
SUBQUERY | 子查询语句的第一个select语句 |
DEPENDENT SUBQUERY | 依赖外部查询的第一个子查询 |
DERIVED | 派生表——该临时表是从子查询派生出来的,位于form中的子查询 |
MATERIALIZED | 物化子查询(不确定啥意思,以后研究后再回来补充,或者大神指教) |
UNCACHEABLE SUBQUERY | 无法缓存结果的子查询,必须为外部查询的每一行重新计算 |
UNCACHEABLE UNION | UNION中的第二个或以后的不可缓存的子查询。 |
table
输出行引用的表的名称。一般为表格名称或别名,也可能为如下值:
1.UNION的并集结果集。
2.derivedN当前行指向派生结果集。可能是一个派生表,例如来自FROM子句的结果集。
3.subqueryN 当前行指向一个子查询的结果集。
type
连接类型。该列输出表示如何连接表。下面的类型表示从最好的到最坏的类型
1.system 该表只有一行(=系统表)。这是const
连接类型的特例 。
2.const 最多只有一行匹配,在查询开始的时候,计算出常量对应的地址,直接访问,例如:select * from test where name ='zhang' 当name是唯一索引的时候,就有可能出现const。const
非常快,因为它只读一次。
3.eq_ref 除了 system
和 const
类型之外,这是最好的连接类型。当两个表联查时使用索引的所有部分(针对的是组合索引),且索引是 主键或唯一索引时使用它。使用“=”运算符来进行索引列的比较。
4.ref 非唯一索引扫描,返回某个匹配值的所有行。常用语非唯一索引。这里对于eq_ref 和ref不熟悉的同学,可以看以下代码:
1 -- 给test表的name字段加唯一索引,test2 的job 行添加非唯一索引。 2 -- 这个代码执行后,首先执行test2 的查询,查出job = ‘teacher’ 的所有集合。 3 -- 所以test2 的typ是ref 表示的是匹配job = ‘teacher’ 的一个结果集。 4 -- 然后从结果集中取出name的集合,去匹配test1.name的结果。因为test1.name是唯一索引,所以一个name最多匹配到一条记录,所以test的type是ref 5 EXPLAIN SELECT 6 * 7 FROM 8 test, 9 test2 10 WHERE 11 test. NAME = test2. NAME 12 AND test2.job = '33'