javaee论坛

普通会员

225648

帖子

345

回复

359

积分

楼主
发表于 2019-11-07 13:21:58 | 查看: 353 | 回复: 2

文章目录前言测试环境EXPLAIN的使用EXPLAIN各列的可能取值idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtraEXPLAIN各列的可能取值对应的例子建表操作(1````````建表操作(2``建表操作(3````建表操作(4``````````````````````````````总结

前言

之前总结了Mysql慢查询日志的开启与配置方法,通过分析慢查询日志可以锁定执行效率差的SQL,但是这仅仅是发现了需要优化的部分,还要分析执行缓慢的原因,这时候就可以使用EXPLAIN命令去分析,所执行的操作究竟慢在哪里,是不是可以通过加索引或者改变查询方法来解决。

通过查询资料发现除了EXPLAIN命令,还有一个DESCRIBE命令,看起来很陌生是不是,但是如果写出简写desc应该很多人的就熟悉了,这不是查询表结构的时候常用的命令吗?实际上以上三个命令在mysql中是等价的,不过在使用时有些习惯性的偏向,通常使用EXPLAIN来分析SQL语句的执行缓慢的问题,而使用DESCRIBE或者desc来查看表的结构,就类似于惯用法,知道就好。

测试环境

Windows10WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis7Serverversion:5.7.21-logMySQLCommunityServer(GPL)Copyright©2000,2018,Oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Type‘help;’or‘\h’forhelp.Type‘\c’toclearthecurrentinputstatement.

EXPLAIN的使用

关于EXPLAIN使用其实很简单,就是在正常的执行语句之前加一个explain就可以了,不过这里也存在一个疑问,就是发现很多篇文章,提到下面这种说法:

explain只能解释select查询,并不会对存储过程、insert、update、delete或其他语句做解释

但是我查阅了官方文档发现,EXPLAIN后面可以跟SELECT、DELETE、INSERT、REPLACE、和UPDATE语句,另外之前使用的EXPLAINEXTENDED选项现在也默认开启,EXTENDED关键字后续会在Mysql8.0版本删除,应该是版本问题导致了explain语句使用的差异,所以请记住在使用新版本的Mysql时,需要分析语句执行情况的,只需要在语句前面添加一个explain关键字即可。

不过在分析select语句时,explain命令会给出额外的提示信息,帮助我们优化查询语句,这也是我们需要学习的重点,先来简单看一下使用方法:

普通的查询语句mysql>select*froma;+----+-----+|id|num|+----+-----+|1|100||2|200||3|300|+----+-----+3rowsinset(0.05sec)使用EXPLAIN来分析普通的查询语句mysql>explainselect*froma;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+|1|SIMPLE|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|NULL|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+1rowinset(0.04sec)

通过上面的例子可以很清楚的知道EXPLAIN命令的使用方法,使用了EXPLAIN关键之后会生成一个分析结果的表格,该表格有id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra一共12列,而这12列中的内容代表的含义是我们学习的重点,也是我们进行优化的依据,这个结果集可能包含多行,其中每一行都是关于一个表的查询信息,可以针对于具体的表查询优化。

本来想每种情况后面紧跟一个例子的,但是发现这样会造成重点内容分散,不利于整体把握,所以还是先把各列可能的取值说清楚,然后在文末针对于上文的取值给出例子,如果看描述就能明白就可以省略例子的内容,否则可以对照着例子的写法理解一下,*[eg:<id-1>]*表示参考后面的例子<id-1>,想对照的话搜索即可。

EXPLAIN各列的可能取值id

id列的取值通常是一组数字,表示select查询的序号,也有可能是一个NULL:

取值含义例子编号id数字相同优先级相同,从上往下执行[eg:<id-1>]id数字不同数字越大优先级越高,越先执行,比如包含子查询的语句,内部查询优先执行[eg:<id-2>]id值为NULL通常是使用了union,表示该行是一个结果集,不需要使用它来进行查询[eg:<id-2>]select_type

select_type列表示查询的类型,主要是用于区分普通查询、联合查询、子查询等复杂的情况:

取值含义例子编号SIMPLE简单的查询语句,查询中不包括UNION操作和子查询[eg:<id-1>]PRIMARY在复杂查询中处于最外层的查询[eg:<id-2>]UNION查询语句中处于UNION关键字之后的查询[eg:<id-2>]DEPENDENTUNION查询语句中处于UNION关键字之后的查询,需要依赖于外部查询[eg:<id-*>]UNIONRESULT表示UNION操作之后的结果,本身并不需要参与查询,通常该记录id字段为NULL[eg:<id-2>]SUBQUERY在子查询中的第一个查询[eg:<id-*>]DEPENDENTSUBQUERY在子查询中的第一个查询,需要依赖于外部查询[eg:<id-*>]DERIVED在FROM列表中包含的子查询[eg:<id-4>]MATERIALIZED物化子查询[eg:<id-5>]UNCACHEABLESUBQUERY一个结果不能被缓存并且对于外部查询的每一行都需要重新评估自身的子查询[eg:<id-*>]UNCACHEABLEUNION查询语句中处于UNION关键字之后的子查询,并且其结果属于UNCACHEABLESUBQUERY类型[eg:<id-*>]table

table列表示查询所引用到的表名,如果查询中使用了别名,那么会显示别名,此外还有一些其他类型的引用:

取值含义例子编号表名、别名查询时引用了这个表[eg:<id-1>]<unionM,N>查询时引用了由id为M和N的两个查询的结果集构成的临时结果集[eg:<id-2>]<derivedN>查询时引用了id为N的查询形成的结果集[eg:<id-4>]<subqueryN>查询时引用了id为N的物化子查询形成的结果集[eg:<id-5>]partitions

partitions列表示查询结果集所涉及到的分区,值为NULL时表示该表并未分区:

取值含义例子编号分区名查询结果集引用到了这个分区[eg:<id-6>]NULL该表格并未分区,或者结果集中数据不再分区中[eg:<id-1>]type

type列表示访问类型,也就是找到所需数据所能使用的最好方式,取值类型很多,在下表中从上到下效果越来越差:

取值含义例子编号NULL查询经过优化执行时不用访问表数据,可能通过索引就搞定了,或者根本没有数据[eg:<id-8>]system在MyISAM类型的表中只有一行数据时出现,如果在Innodb类型表中只有一行数据通常显示ALL[eg:<id-9>]const表格使用了唯一索引或者主键,并且将其作为判定相等的筛选条件,得到一条记录[eg:<id-10>]eq_ref连接查询时,驱动表的每一条记录的条件列,与后面连接表的主键或唯一索引判定相等,后表采用的连接方式[eg:<id-11>]ref连接查询时,驱动表的每一条记录的条件列,与后面连接表的索引列判定相等,后表采用的连接方式,索引列数据不要求唯一,不连接表时就是查索引列等于一个具体的值[eg:<id-7>]ref_or_null与ref基本一致,另外包含查询索引列为NULL的记录[eg:<id-12>]fulltext包含全文索引的表的查询方式,全文索引的优先级要高于普通索引[eg:<id-*>]index_merge至少用到了两个索引,并且用到了索引合并优化[eg:<id-*>]unique_subquerywhere条件in形式的子查询子查询返回唯一结果时,等价于将类型为eq_ref的查询作为子查询[eg:<id-*>]index_subquerywhere条件in形式的子查询引用了非唯一索引,等价于将类型为ref的查询作为子查询[eg:<id-*>]range对于表的索引列使用范围判定的查询[eg:<id-13>]index除了查找索引树之外,与ALL选项基本一致,通常由于索引较小查询会快一点[eg:<id-14>]ALL完整浏览整个表格,查找符合条件的结果,属于最差的访问方式[eg:<id-1>]possible_keys

possible_keys列表示查询所需数据过程可能用到的索引名,具体是否使用还要依赖于查询过程中表的连接顺序,该值为NULL时表示无索引可用,此时需要考虑对表进行优化来改善查询结果情况了。

取值含义例子编号索引名查询时可能用到的索引名,是否使用取决于查询连接顺序[eg:<id-7>]NULL该查询没有可用索引,需要考虑优化[eg:<id-1>]key

key列表示查询所需数据过程确实用到的索引名,该值为NULL时表示无索引可用,此时也需要考虑对表进行优化。

取值含义例子编号索引名查询时确实用到的索引名[eg:<id-7>]NULL查询时没有可用索引,需考虑优化[eg:<id-1>]key_len

key_len列表示查询所需数据过程用到的索引长度,该值为NULL时表示没有使用索引,由于存储格式的不同,对于可以为NULL的列储存索引所需空间要比不能为NULL列的大一个字节。

取值含义例子编号索引长度查询时确实用到的索引长度[eg:<id-7>]NULL没有使用到索引[eg:<id-1>]ref

key_len列表示查询时使用常数或者某一列来和索引列比较,有时会显示func,表示使用了一些函数的结果与索引比较,值为NULL时表示没用到索引比较

取值含义例子编号引用列名查询时与索引比较的列名,形式可能为<subquery2>.id,表示引用了子查询结果中的id列[eg:<id-5>]const查询时与索引比较的为常数[eg:<id-10>]func查询时与索引比较的一些函数结果[eg:<id-*>]NULL不是上述几种情况,可能没有使用索引比较[eg:<id-1>]rows

rows列表示查询符合条件的结果时所要检查的数据行数,在InnoDB类型的表中,这个值是一个估计值,可用来参考并不精确,值为NULL时表示表中无数据,或者无法找到匹配行,比如查找一条主键中不包含的数据。

取值含义例子编号数字查询时所要检查的数据行数[eg:<id-3>]NULL没有数据或者不需要检测[eg:<id-1>]filtered

filtered列表示通过筛选条件的记录数占可能参与检查的记录数,是一个估计值,该值与rows的乘积大概就是结果集中的记录数:

取值含义例子编号数字通过筛选条件的记录数占可能参与检查的记录数,最大为100.00[eg:<id-3>]Extra

Extra列表示Mysql处理查询所使用的额外信息,类型很多,其中一些情况是需要进行优化的信号,对于SQL分析很有帮助:

取值含义例子编号Childof'tbl_name'pushedjoin@1当表被当做另一个表’tbl_name’的子表能被存放在NDB内核的时候,该值只出现在存储选项被开启的NDB集群上-constrownotfound当一个系统表没有数据可查的时候-Deletingallrows对于DELETE操作,MyISAM引擎支持一个可以简单快速删除表数据的方法,如果使用了整个优化则显示此选项-Distinct查询时使用了distinct关键字,当查找到一个第一个匹配值后,相同匹配就不再搜索了-const当一个系统表没有数据可查的时候-FirstMatch(tbl_name)当semi-joinFirstMatch访问简化策略被使用时候,通常出现在Where的in子句中,找到一个值后,后面相同值不再匹配出现-FullscanonNULLkey当优化器不能使用索引查找访问方法时,将会显示该值,表示将子查询作为一种后备策略-ImpossibleHAVING当HAVING子句的条件总是不成立,无法匹配出任何数据[eg:<id-23>]ImpossibleWHERE当WHERE子句的条件总是不成立,无法匹配出任何数据[eg:<id-22>]ImpossibleWHEREnoticedafterreadingconsttables在读取const表和system表时,WHERE子句的条件总是不成立-LooseScan(m..n)当semi-joinLooseScan策略被使用的时候.m和n是索引的编号-Nomatchingmin/maxrow在查询中包括系统函数,但是通过条件查询无法匹配出数据的时候,比如SELECTMIN(...)FROM...WHERECONDITION-nomatchingrowinconsttable当连表查询时有一个空表或者没有匹配唯一索引的数据时,会给出此提示[eg:<id-18>]Notablesused当查询中没有FROM子句或者只有FROMDUAL子句时[eg:<id-20>]Notexists发生在左外连接的优化,当要求右侧表字段为空时,如果查找到一条不为空匹配,则停止查找匹配这项记录,比如SELECT*FROMt1LEFTJOINt2ONt1.id=t2.idWHEREt2.idISNULL-Planisn'treadyyet执行命令EXPLAINFORCONNECTION时,优化器在命名连接中还没有完成为语句执行创建执行计划-Rangecheckedforeachrecord(indexmap:N)当没有好的默认索引可使用时,但当我们可以将以前表中的所有列都视为常量时,可能会使用某些索引就是这种情况-ScannedNdatabases表示在执行对INFORMATION_SCHEMA表的查询时,服务器执行了多少次目录扫描,数字可以是0,1或者任何整数-Selecttablesoptimizedaway优化器发现只有一行,并且通过索引直接皆可以获得想要的数据,而不需要真正访问表数据,比如在索引列使用聚合函数[eg:<id-16>]Skip_open_table对于INFORMATION_SCHEMA表的查询,不需要打开表,只需要浏览目录就可以完成查询-Open_frm_only对于INFORMATION_SCHEMA表的查询,需要打开.frm文件完成查询-Open_full_table对于INFORMATION_SCHEMA表的查询,需要打开.frm,.MYD,.MYI文件完成查询-Starttemporary,Endtemporary表示使用临时表用于semi-joinDuplicateWeedout策略[eg:<id-15>]uniquerownotfound当一个拥有UNIQUE索引或者PRIMARY索引的表没有查到满足条件数据时-Usingfilesort无法仅通过引用索引就完成排序,需要一个额外的阶段来进行外部排序,并且按排序结果取回记录[eg:<id-17>]Usingindex只通过索引排序就可以取得排序后的数据,无需做额外的搜索真实记录数据的工作[eg:<id-7>]Usingindexcondition首先通过访问索引元组的方式来读取表格,除非必要时会通过索引索引信息延迟读取整个表格数据-Usingindexforgroup-by索引用于处理包含GROUPBY和DISTINCT的查询,由于重复项会被快速跳过。所以非常高效-Usingjoinbuffer(BlockNestedLoop)连接访问之前表格数据被部分读入连接缓存区,然后使用缓存中的行与当前表进行连接,括号内容为使用算法[eg:<id-1>]Usingjoinbuffer(BatchedKeyAccess)连接访问之前表格数据被部分读入连接缓存区,然后使用缓存中的行与当前表进行连接,括号内容为使用算法-UsingMRR表格数据会通过Multi-RangeRead优化策略来读取-Usingsort_union(...),Usingunion(...),Usingintersect(...)针对于index_merge选项,表明索引浏览被合并的特定算法-Usingtemporary需要创建一个临时表来存储结果,通常出现在包含了作用在不同列的上的GROUPBY子句和ORDERBY子句[eg:<id-2>]Usingwhere当查询使用了WHERE子句来过滤结果发送给客户端的时候[eg:<id-3>]Usingwherewithpushedcondition仅适用于NDB类型表,它意味着NDB集群正在使用“条件存储”优化选项来提高接近于非索引列和常量之间直接比较的效率。-Zerolimit当查询语句包含LIMIT0子句并不能查到任何记录的时候[eg:<id-19>]EXPLAIN各列的可能取值对应的例子建表操作(1

为了展示id取值的不同先创建a、b两个表,然后插入测试数据,由于是测试的开始,我们分别查看表结构和数据,之后为了减少篇幅,只给出命令,不再查询表结构和数据,接着我们开始测试:

mysql>createtablea(idint,numint);QueryOK,0rowsaffected(0.04sec)mysql>insertintoavalues(1,100),(2,200),(3,300);QueryOK,3rowsaffected(0.01sec)Records:3Duplicates:0Warnings:0mysql>desca;+-------+---------+------+-----+---------+-------+|Field|Type|Null|Key|Default|Extra|+-------+---------+------+-----+---------+-------+|id|int(11)|YES||NULL|||num|int(11)|YES||NULL||+-------+---------+------+-----+---------+-------+2rowsinset(0.02sec)mysql>select*froma;+----+-----+|id|num|+----+-----+|1|100||2|200||3|300|+----+-----+3rowsinset(0.02sec)mysql>createtableb(idint,numint);QueryOK,0rowsaffected(0.03sec)mysql>insertintobvalues(1,100),(2,200),(4,400);QueryOK,3rowsaffected(0.00sec)Records:3Duplicates:0Warnings:0mysql>descb;+-------+---------+------+-----+---------+-------+|Field|Type|Null|Key|Default|Extra|+-------+---------+------+-----+---------+-------+|id|int(11)|YES||NULL|||num|int(11)|YES||NULL||+-------+---------+------+-----+---------+-------+2rowsinset(0.03sec)mysql>select*fromb;+----+-----+|id|num|+----+-----+|1|100||2|200||4|400|+----+-----+3rowsinset(0.03sec)<id-1>mysql>explainselect*froma,b;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+|1|SIMPLE|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|NULL||1|SIMPLE|b|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|Usingjoinbuffer(BlockNestedLoop)|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+2rowsinset(0.05sec)<id-2>mysql>explainselect*fromaunionselect*fromb;+------+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+------+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+|1|PRIMARY|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|NULL||2|UNION|b|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|NULL||NULL|UNIONRESULT|<union1,2>|NULL|ALL|NULL|NULL|NULL|NULL|NULL|NULL|Usingtemporary|+------+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+3rowsinset(0.05sec)<id-3>mysql>explainselectidfromawhereid=(selectidfrombwherenum=100);+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|1|PRIMARY|a|NULL|ALL|NULL|NULL|NULL|NULL|3|33.33|Usingwhere||2|SUBQUERY|b|NULL|ALL|NULL|NULL|NULL|NULL|3|33.33|Usingwhere|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+2rowsinset(0.06sec)<id-4>mysql>select@@version;+-----------+|@@version|+-----------+|5.6.33|+-----------+1rowinset(0.05sec)mysql>explainselectnumfrom(select*froma)twheret.id>1;+----+-------------+------------+------+---------------+------+---------+------+------+-------------+|id|select_type|table|type|possible_keys|key|key_len|ref|rows|Extra|+----+-------------+------------+------+---------------+------+---------+------+------+-------------+|1|PRIMARY|<derived2>|ALL|NULL|NULL|NULL|NULL|3|Usingwhere||2|DERIVED|a|ALL|NULL|NULL|NULL|NULL|3|NULL|+----+-------------+------------+------+---------------+------+---------+------+------+-------------+2rowsinset(0.06sec)--很神奇的是我在5.7版本操作了半天也没出现,内部进行了优化,相同的语句操作如下:mysql>select@@version;+------------+|@@version|+------------+|5.7.21-log|+------------+1rowinset(0.05sec)mysql>explainselectnumfrom(select*froma)twheret.id>1;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|1|SIMPLE|a|NULL|ALL|NULL|NULL|NULL|NULL|3|33.33|Usingwhere|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1rowinset(0.05sec)建表操作(2

新建两个带索引的表格c和d,其中表格c带有普通索引,表格d带有主键,这两个表格会参与后面用作展示的例子:

mysql>createtablec(idint,numint,keyidindex(id));QueryOK,0rowsaffected(0.21sec)mysql>insertintocvalues(1,103),(2,203),(6,603);QueryOK,3rowsaffected(0.05sec)Records:3Duplicates:0Warnings:0mysql>createtabled(idint,numint,primarykey(id));QueryOK,0rowsaffected(0.14sec)mysql>insertintodvalues(1,104),(2,204),(6,504);QueryOK,3rowsaffected(0.11sec)Records:3Duplicates:0Warnings:0<id-5>mysql>explainselectidfromdwhereidin(selectidfroma);+----+--------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+--------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+|1|SIMPLE|<subquery2>|NULL|ALL|NULL|NULL|NULL|NULL|NULL|100.00|Usingwhere||1|SIMPLE|d|NULL|eq_ref|PRIMARY|PRIMARY|4|<subquery2>.id|1|100.00|Usingindex||2|MATERIALIZED|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|NULL|+----+--------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+3rowsinset(0.05sec)建表操作(3

为了测试partitions字段的取值,创建表格p,其实就是创建了一个带有分区的表,这个表格会参与后面用作展示的例子:

mysql>createtablep(idint,numint)partitionbyrange(id)(partitionp0valueslessthan(3),partitionp1valueslessthan(6));QueryOK,0rowsaffected(0.02sec)mysql>insertintopvalues(1,111),(2,222),(4,444),(5,555);QueryOK,4rowsaffected(0.01sec)Records:4Duplicates:0Warnings:0<id-6>mysql>explainselect*frompwhereid<5;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+|1|SIMPLE|p|p0,p1|ALL|NULL|NULL|NULL|NULL|4|33.33|Usingwhere|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1rowinset(0.05sec)<id-7>mysql>explainselectidfromcwhereid=1;+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+|1|SIMPLE|c|NULL|ref|idindex|idindex|5|const|1|100.00|Usingindex|+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------------+1rowinset(0.06sec)建表操作(4

为了测试type字段的取值,有时需要特定的数据引擎才可以,所以创建了以MyISAM引擎类型的表格m,然后进行一些测试:

mysql>createtablem(idint,numint)engine=myisam;QueryOK,0rowsaffected(0.02sec)<id-8>mysql>explainselect*fromm;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|nomatchingrowinconsttable|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+1rowinset(0.03sec)<id-9>mysql>insertintomvalues(1,1001);QueryOK,1rowaffected(0.00sec)mysql>explainselect*fromm;+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+|1|SIMPLE|m|NULL|system|NULL|NULL|NULL|NULL|1|100.00|NULL|+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+1rowinset(0.04sec)<id-10>mysql>explainselectidfromdwhereid=1;+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+|1|SIMPLE|d|NULL|const|PRIMARY|PRIMARY|4|const|1|100.00|Usingindex|+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+1rowinset(0.04sec)<id-11>mysql>explainselecta.idfroma,dwherea.id=d.id;+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+-------------+|1|SIMPLE|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|Usingwhere||1|SIMPLE|d|NULL|eq_ref|PRIMARY|PRIMARY|4|sqltest2.a.id|1|100.00|Usingindex|+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+-------------+2rowsinset(0.05sec)<id-12>mysql>explainselectidfromcwhereid=1oridisnull;+----+-------------+-------+------------+-------------+---------------+---------+---------+-------+------+----------+--------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+-------------+---------------+---------+---------+-------+------+----------+--------------------------+|1|SIMPLE|c|NULL|ref_or_null|idindex|idindex|5|const|2|100.00|Usingwhere;Usingindex|+----+-------------+-------+------------+-------------+---------------+---------+---------+-------+------+----------+--------------------------+1rowinset(0.04sec)<id-13>mysql>explainselectidfromcwhereid>1;+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+|1|SIMPLE|c|NULL|range|idindex|idindex|5|NULL|2|100.00|Usingwhere;Usingindex|+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+1rowinset(0.04sec)<id-14>mysql>explainselectidfromc;+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+|1|SIMPLE|c|NULL|index|NULL|idindex|5|NULL|3|100.00|Usingindex|+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+1rowinset(0.03sec)<id-15>mysql>explainselectidfromcwhereidin(selecta.idfroma,dwherea.id=d.id);+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+------------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+------------------------------+|1|SIMPLE|a|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|Usingwhere;Starttemporary||1|SIMPLE|c|NULL|ref|idindex|idindex|5|sqltest2.a.id|1|100.00|Usingindex||1|SIMPLE|d|NULL|eq_ref|PRIMARY|PRIMARY|4|sqltest2.a.id|1|100.00|Usingindex;Endtemporary|+----+-------------+-------+------------+--------+---------------+---------+---------+---------------+------+----------+------------------------------+3rowsinset(0.04sec)<id-16>mysql>explainselectmin(id)fromc;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|Selecttablesoptimizedaway|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+1rowinset(0.05sec)<id-17>mysql>explainselectidfromcorderbynum;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+|1|SIMPLE|c|NULL|ALL|NULL|NULL|NULL|NULL|3|100.00|Usingfilesort|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+1rowinset(0.04sec)<id-18>mysql>explainselectidfromdwhereid=100;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|nomatchingrowinconsttable|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+1rowinset(0.04sec)<id-19>mysql>explainselectidfromdlimit0;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|Zerolimit|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------+1rowinset(0.04sec)<id-20>mysql>explainselect1fromdual;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|Notablesused|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+1rowinset(0.04sec)<id-22>mysql>explainselect*fromawhere1=2;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|ImpossibleWHERE|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+1rowinset(0.03sec)<id-23>mysql>explainselectsum(num)fromagroupbyidhaving1=2;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------+|1|SIMPLE|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|ImpossibleHAVING|+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------+1rowinset(0.04sec)总结关于EXPLAIN命令的所有可能取值后面,还有部分例子是空的,完全是由于个人水平有限,等找到所说的取值情况再补充,也欢迎大家提供例子另外EXPLAIN提供的信息中没有关于触发器、存储过程的信息或者评估用户自定义函数对查询的影响情况所有的可能取值中possible_keys、rows、filtered中的统计信息基本是估算的,并非精确值,只能用来做优化参考Extra列的信息对于尝试优化起到了至关重要的作用,当出现Usingfilesort、Usingtemporary、Usingjoinbuffer的时候一般就要考虑采取优化方案了首先了解这些可能出现的情况,之后我们留这里利用这些说明来进行查询优化了

上一篇:Numpy基础(2) 下一篇:Numpy(3)

普通会员

0

帖子

300

回复

308

积分
沙发
发表于 2023-11-06 06:27:51

百因必有果你的报应就是我

普通会员

0

帖子

293

回复

299

积分
板凳
发表于 2023-11-20 02:48:48

记录一下

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017