SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。
用法简介
EXPLAIN的用法很简单,只需要在你的SQL前面加上EXPLAIN即可。例如:
explainselect*fromt;
PS:insert、update、delete同样可以通过explain查看执行计划,不过通常我们更关心select的执行情况
你会看到如下输出:
执行计划结果字段说明如下表:
EXPLAIN的用法非常简单,看一眼就会。但是要根据输出结果找到问题并解决,就没那么容易了。就好比操作拍CT的机器可能相对简单,但要从CT成像中看出问题并给出治疗方案就需要丰富的知识和大量的临床经验了。
因此,我们需要知道每个字段代表什么指标;什么样的取值是我们想要的,什么样是需要优化的;最后还要知道如何优化成我们想要的值。
字段详解
id
标识符。查询操作的序列号。通常都是正整数,但当有UNION操作时,该值可以为NULL。
id相同
explainselect*fromt1wheret1.idin(selectt2.idfromt2);
id不同
explainselect*fromt1wheret1.id=(selectt2.idfromt2);
id包含NULL
explainselectidfromt1union(selectidfromt2);
id为NULL时,table列值为unionM,n格式,表示该行为id为m和n联合的结果
id顺序的规则:如果id相同,执行顺序由上到下;如果不同,执行顺序由大到小。
select_type
SELECT类型,常见的取值如下表:
UNION或者子查询MySQL会自动产生临时表。派生表可以简单理解为具有别名的临时表。生成临时表的这个动作称为物化(水变成蒸汽叫汽化)
临时表通常在内存里,当其size超过一定范围会被存入磁盘
#临时表select*fromt1joint2ont1.id=t2.idwheret1.id1;#派生表,临时表取个别名select*from(select*fromt1)t;
type
连接字段为主键或者唯一索引,此类型通常出现于多表的join查询,表示对于前表的每一个结果,都对应后表的唯一一条结果。并且查询的比较是=操作,查询效率比较高。
还有一种NULL的情况,比如selectmin(id)fromt1,但MySQL官方没有提及这种情况,所以我们不在此讨论
性能从优到劣依次为:
systemconsteq_refreffulltextref_or_nullindex_mergeunique_subqueryindex_subqueryrangeindexALL
优化原则:最好做到const,至少做到ref,避免ALL
ref
查询中用来和索引比较的类型,如:id=1,值为const;如果是联合查询或者子查询则为关联的字段;如果使用了函数,则为func。
Extra
Extra用来存放一些附加信息,通常用来配合type的输出来做SQL优化。
扩展
desc
desc与explain作用相同,可以互相代替,后面的例子中均使用desc来查看执行计划。
format
explain/desc还支持一些参数,format顾名思义,是用来格式化输出结果的。它包括两种格式化方式:tree和json。
比如:
descformat=treeselect*fromt1wheret1.idin(selectt2.idfromt2wheret2.id1);
输出格式如下:
执行计划结果以树形结构展示,可以清晰的看出语句之间的嵌套关系,还有基本的执行成本(cost)。
使用json方式:
descformat=jsonselect*fromt1;
输出结构为一个JSON结构:
+---------------------------------------------------+
EXPLAIN
+---------------------------------------------------+
{"query_block":{"select_id":1,"cost_info":{"query_cost":"0.35"},"table":{"table_name":"t1","access_type":"ALL","rows_examined_per_scan":1,"rows_produced_per_join":1,"filtered":".00","cost_info":{"read_cost":"0.25","eval_cost":"0.10","prefix_cost":"0.35","data_read_per_join":"56"},"used_columns":["id","a1","b1"]}}}
+---------------------------------------------------+1rowinset,1warning(0.00sec)
简介表中的JSONName指的就是这里JSON结果的key
json格式会展示出更加详细的信息,可以看到执行成本划分的更加细致了,方便定位到慢SQL的问题具体出现在哪个环节。
analyze
除了format以外,explain/desc还可以使用analyze参数:
descanalyzeselect*fromt1wheret1.idin(selectt2.idfromt2wheret2.id1);
输出结果:
可以看出,analyze的输出结果是基于format=tree的
上面执行计划中(format=json/tree)的执行成本(cost)都是估值,而analyze中的执行成本是真实值。actualtime代表对应SQL执行的真实时间,单位为毫秒。
最后
执行计划的结果中,我们最关心的是type,它能够最直接的反映出SQL执行效率处在什么级别。然后再结合其他字段(例如Extra)来做更细致的分析。还可以通过各种参数,来分解每个环节的执行情况。
今天的内容就到这里,有哪些想要了解的可以留言告诉我。