MySQL作为目前服务端使用率最高的开源关系型数据库,它的性能优化是很多开发者和DBA非常关注的话题和工作重点。既然说到MySQL优化那就不得不去了解执行一条SQL语句后MYSQL引擎到底在背后做了哪些操作了,比如说使用了哪些数据进行查询,做了什么运算,以什么样的方式来进行数据查询,以及数据的排序方式是什么。如果对于这些操作没有一个较为清晰的概念的话,那么对于MYSQL优化也就无从谈起了。
那么我们如何来了解SQL执行后MySQL究竟进行了哪些操作呢?这个时候explain就闪亮登场了,只需要通过在需要执行的SQL之前加上EXPLAIN MYSQL就会输出当前语句的执行计划,也就是我们想知道的MYSQL执行SQL语句背后的操作。
举个栗子:
mysql> EXPLAIN SELECT * FROM `test`;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | test | index | NULL | PRIMARY | 4 | NULL | 1 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
如上所示,就是EXPLAIN语句的执行效果,explain一共返回12列信息:id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra那么接下来奶嘴就来为大家聊聊EXPLAIN结果中的字段所表述的操作以及字段对应输出值的含义。
id
1、如果行记录的id值都一样则表示查询顺序是之上而下的。
2、如果id值一样则可以认为是同一组查询
3、id值不一样则表示可能存在子查询,如果输出null可能存在union查询,id值不一样的情况下id值越大则表示执行的顺序越靠前。
select_type
表示查询查询类型,在MySQL中该字段有12种返回结果,分别如下:
SIMPLE简单查询,标识查询不包含任何子查询或者UNION语句
PRIMARY复杂查询的外层查询,一般都在第一行,代表这是一个复杂查询的最外层查询
UNIONUNION中的第二个或后面的SELECT语句
DEPENDENT UNION复杂查询中,依赖外部查询的UNION子句查询
UNION RESULT复杂查询中,UNION的结果,这是一个从匿名临时表检索最终结果的查询
SUBQUERY子查询中的第一个
DEPENDENT SUBQUERY子查询的第一个,依赖外部查询的
DERIVEDSELECT, FROM子句的子查询
DEPENDENT DERIVED依赖于另一张表的派生表查询
MATERIALIZED复杂查询中,具体化的视图子查询
UNCACHEABLE SUBQUERY不可缓存的子查询
UNCACHEABLE UNION不可缓存的UNION子查询
table
这个字段比较简单,表示对应语句访问的哪张表。
NULL 表示与数据库无关的内容,即SELECT NOW()之类的
表示由UNION操作产生的临时表,其中M和N表示产生临时表的源表的id
表示是由id为M的表派生而来的临时表
表示是由id为M的子查询具体化而来的临时表
type
这个字段在性能优化中想需要格外关注,由于篇幅比较长,奶嘴单独开一篇文章做详细介绍《mysql执行计划分析(explain)的type字段的详细介绍说明》,这里先简单的做个说明。一般type字段会出现以下值:
system:特殊类型的const,表只有一行记录是会出现。
const:只有一行记录被匹配是会出现,例如使用的唯一索引和主键索引。
eq_ref:性能良好的连接查询,对于前面结果的每一行都只有一条匹配记录。
ref:比eq_ref性能要差,表示对于结果,每一行都有多条记录匹配。
fulltext:全文索引
ref_or_null:和ref差不多,只不过当索引可以为null时,条件中出现了IS NULL或IS NOT NULL时就会出现这种情况。
index_merge:多个索引合并。
unique_subquery:子查询返回了多行结果,但是每行结果只匹配一条记录。
index_subquery:子查询返回了多行结果,但是每行结果都匹配了多个值。
range:范围类型的查询。
index:和all类型的全表扫描差不多
all:全表扫描
possible_keys
这个字段表示可能会用到的索引。
key
这个字段表示实际用到的索引。
key_len
所使用的索引的最大长度,比如一个int字段len就是4字节长度,当然如果把它理解为索引字段的数据类型字节长度也不太对,这个因为这个长度还和是否可以为null有关,可以为null的话则key_len等于数据类型的字节长度+1.
ref
显示哪些列或者常量被用来跟key中显示的索引进行比较,从而获取结果,如果显示func,则说明是某些function的结果被用来进行比较。
rows
表示mysql需要得到结果需要扫描的预计行数,这个值不是一个精准值。
filtered
使用EXPLAIN EXTENDED才会显示的列,用百分比表示有多少行会被过滤出来去与之前的表关联rows * filtered / 100 就能得到行数。
Extra
这一列输出的是一些额外的信息,不过在SQL语句优化中也是很重要的一个字段,奶嘴单独开了篇文章进行讲解《MySQL执行计划分析(EXPLAIN)之Extra字段详细介绍说明》。
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,非商业性质可转载须署名链接,详见本站版权声明。